shithub: sox

Download patch

ref: 6a8f279668d0cd65f15fb48b68b2b182507bbbec
parent: 8e668058eaedc563b3d14ce1c364abaca3907c98
author: robs <robs>
date: Sat May 26 08:11:21 EDT 2007

sox namespace fixes; handler/driver convergence; other clean-ups

--- a/src/alsa.c
+++ b/src/alsa.c
@@ -1,4 +1,4 @@
-/* ALSA sound driver
+/* ALSA sound handler
  *
  * Copyright 1997-2005 Jimen Ching And Sundry Contributors
  * This source code is freely redistributable and may be used for
--- a/src/amr.h
+++ b/src/amr.h
@@ -155,11 +155,11 @@
 const sox_format_t *AMR_FORMAT_FN(void)
 {
   static char const * names[] = {AMR_NAMES, NULL};
-  static sox_format_t driver = {
+  static sox_format_t handler = {
     names, 0,
     startread, read, stopread,
     startwrite, write, stopwrite,
     sox_format_nothing_seek
   };
-  return &driver;
+  return &handler;
 }
--- a/src/avr.c
+++ b/src/avr.c
@@ -1,6 +1,6 @@
 /*
 
-    AVR file format driver for SoX
+    AVR file format handler for SoX
     Copyright (C) 1999 Jan Paul Schmidt <jps@fundament.org>
 
     This library is free software; you can redistribute it and/or
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -31,7 +31,7 @@
 static char const all_width_types[] = "hboqs";
 
 
-int sox_biquad_getopts(eff_t effp, int n, char **argv,
+int sox_biquad_getopts(sox_effect_t effp, int n, char **argv,
     int min_args, int max_args, int fc_pos, int width_pos, int gain_pos,
     char const * allowed_width_types, filter_t filter_type)
 {
@@ -45,7 +45,7 @@
       (n > width_pos && ((unsigned)(sscanf(argv[width_pos], "%lf%c %c", &p->width, &width_type, &dummy)-1) > 1 || p->width <= 0)) ||
       (n > gain_pos  && sscanf(argv[gain_pos], "%lf %c", &p->gain, &dummy) != 1) ||
       !strchr(allowed_width_types, width_type) || (width_type == 's' && p->width > 1)) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   p->width_type = strchr(all_width_types, width_type) - all_width_types;
@@ -55,7 +55,7 @@
 }
 
 
-int sox_biquad_start(eff_t effp)
+int sox_biquad_start(sox_effect_t effp)
 {
   biquad_t p = (biquad_t) effp->priv;
 
@@ -80,7 +80,7 @@
       "semilogx(w,20*log10(h))\n"
       "disp('Hit return to continue')\n"
       "pause\n"
-      , effp->name, p->gain, p->fc, width_str[p->width_type], p->width
+      , effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width
       , effp->ininfo.rate, effp->ininfo.rate
       , p->b0, p->b1, p->b2, p->a1, p->a2
       );
@@ -101,7 +101,7 @@
       "set key off\n"
       "plot [f=10:Fs/2] [-35:25] 20*log10(H(f))\n"
       "pause -1 'Hit return to continue'\n"
-      , effp->name, p->gain, p->fc, width_str[p->width_type], p->width
+      , effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width
       , effp->ininfo.rate, effp->ininfo.rate
       , p->b0, p->b1, p->b2, p->a1, p->a2
       );
@@ -113,7 +113,7 @@
 }
 
 
-int sox_biquad_flow(eff_t effp, const sox_ssample_t *ibuf,
+int sox_biquad_flow(sox_effect_t effp, const sox_ssample_t *ibuf,
     sox_ssample_t *obuf, sox_size_t *isamp, sox_size_t *osamp)
 {
   biquad_t p = (biquad_t) effp->priv;
--- a/src/biquad.h
+++ b/src/biquad.h
@@ -74,14 +74,14 @@
 assert_static(sizeof(struct biquad) <= SOX_MAX_EFFECT_PRIVSIZE, 
     /* else */ biquad_PRIVSIZE_too_big);
 
-int sox_biquad_getopts(eff_t effp, int n, char **argv,
+int sox_biquad_getopts(sox_effect_t effp, int n, char **argv,
     int min_args, int max_args, int fc_pos, int width_pos, int gain_pos,
     char const * allowed_width_types, filter_t filter_type);
-int sox_biquad_start(eff_t effp);
-int sox_biquad_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+int sox_biquad_start(sox_effect_t effp);
+int sox_biquad_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                         sox_size_t *isamp, sox_size_t *osamp);
 
 #undef sox_fail
-#define sox_fail sox_message_filename=effp->name,sox_fail
+#define sox_fail sox_message_filename=effp->handler.name,sox_fail
 
 #endif
--- a/src/biquads.c
+++ b/src/biquads.c
@@ -64,13 +64,13 @@
 #include <math.h>
 
 
-static int hilo1_getopts(eff_t effp, int n, char **argv) {
+static int hilo1_getopts(sox_effect_t effp, int n, char **argv) {
   return sox_biquad_getopts(effp, n, argv, 1, 1, 0, 1, 2, "",
-      *effp->name == 'l'? filter_LPF_1 : filter_HPF_1);
+      *effp->handler.name == 'l'? filter_LPF_1 : filter_HPF_1);
 }
 
 
-static int hilo2_getopts(eff_t effp, int n, char **argv) {
+static int hilo2_getopts(sox_effect_t effp, int n, char **argv) {
   biquad_t p = (biquad_t) effp->priv;
   if (n != 0 && strcmp(argv[0], "-1") == 0)
     return hilo1_getopts(effp, n - 1, argv + 1);
@@ -78,11 +78,11 @@
     ++argv, --n;
   p->width = sqrt(0.5); /* Default to Butterworth */
   return sox_biquad_getopts(effp, n, argv, 1, 2, 0, 1, 2, "qoh",
-      *effp->name == 'l'? filter_LPF : filter_HPF);
+      *effp->handler.name == 'l'? filter_LPF : filter_HPF);
 }
 
 
-static int bandpass_getopts(eff_t effp, int n, char **argv) {
+static int bandpass_getopts(sox_effect_t effp, int n, char **argv) {
   filter_t type = filter_BPF;
   if (n != 0 && strcmp(argv[0], "-c") == 0)
     ++argv, --n, type = filter_BPF_CSG;
@@ -90,12 +90,12 @@
 }
 
 
-static int bandrej_getopts(eff_t effp, int n, char **argv) {
+static int bandrej_getopts(sox_effect_t effp, int n, char **argv) {
   return sox_biquad_getopts(effp, n, argv, 2, 2, 0, 1, 2, "hqob", filter_notch);
 }
 
 
-static int allpass_getopts(eff_t effp, int n, char **argv) {
+static int allpass_getopts(sox_effect_t effp, int n, char **argv) {
   filter_t type = filter_APF;
   int m;
   if (n != 0 && strcmp(argv[0], "-1") == 0)
@@ -107,21 +107,21 @@
 }
 
 
-static int tone_getopts(eff_t effp, int n, char **argv) {
+static int tone_getopts(sox_effect_t effp, int n, char **argv) {
   biquad_t p = (biquad_t) effp->priv;
   p->width = 0.5;
-  p->fc = *effp->name == 'b'? 100 : 3000;
+  p->fc = *effp->handler.name == 'b'? 100 : 3000;
   return sox_biquad_getopts(effp, n, argv, 1, 3, 1, 2, 0, "shqo",
-      *effp->name == 'b'?  filter_lowShelf: filter_highShelf);
+      *effp->handler.name == 'b'?  filter_lowShelf: filter_highShelf);
 }
 
 
-static int equalizer_getopts(eff_t effp, int n, char **argv) {
+static int equalizer_getopts(sox_effect_t effp, int n, char **argv) {
   return sox_biquad_getopts(effp, n, argv, 3, 3, 0, 1, 2, "qoh", filter_peakingEQ);
 }
 
 
-static int band_getopts(eff_t effp, int n, char **argv) {
+static int band_getopts(sox_effect_t effp, int n, char **argv) {
   filter_t type = filter_BPF_SPK;
   if (n != 0 && strcmp(argv[0], "-n") == 0)
     ++argv, --n, type = filter_BPF_SPK_N;
@@ -129,7 +129,7 @@
 }
 
 
-static int deemph_getopts(eff_t effp, int n, char **argv) {
+static int deemph_getopts(sox_effect_t effp, int n, char **argv) {
   biquad_t p = (biquad_t) effp->priv;
   p->fc    = 5283;
   p->width = 0.4845;
@@ -138,7 +138,7 @@
 }
 
 
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
   biquad_t p = (biquad_t) effp->priv;
   double w0 = 2 * M_PI * p->fc / effp->ininfo.rate;
@@ -312,12 +312,12 @@
 
 
 #define BIQUAD_EFFECT(name,group,usage,flags) \
-sox_effect_t const * sox_##name##_effect_fn(void) { \
-  static sox_effect_t driver = { \
+sox_effect_handler_t const * sox_##name##_effect_fn(void) { \
+  static sox_effect_handler_t handler = { \
     #name, "Usage: " #name " " usage, flags, \
     group##_getopts, start, sox_biquad_flow, 0, 0, 0, \
   }; \
-  return &driver; \
+  return &handler; \
 }
 
 BIQUAD_EFFECT(highp,     hilo1,    "cutoff-frequency", SOX_EFF_DEPRECATED)
--- a/src/chorus.c
+++ b/src/chorus.c
@@ -71,8 +71,6 @@
 #define MOD_TRIANGLE    1
 #define MAX_CHORUS      7
 
-static sox_effect_t sox_chorus_effect;
-
 typedef struct chorusstuff {
         int     num_chorus;
         int     modulation[MAX_CHORUS];
@@ -92,7 +90,7 @@
 /*
  * Process options
  */
-static int sox_chorus_getopts(eff_t effp, int n, char **argv) 
+static int sox_chorus_getopts(sox_effect_t effp, int n, char **argv) 
 {
         chorus_t chorus = (chorus_t) effp->priv;
         int i;
@@ -102,7 +100,7 @@
 
         if ( ( n < 7 ) || (( n - 2 ) % 5 ) )
         {
-            sox_fail(sox_chorus_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
 
@@ -124,7 +122,7 @@
                         chorus->modulation[chorus->num_chorus] = MOD_TRIANGLE;
                 else
                 {
-                        sox_fail(sox_chorus_effect.usage);
+                        sox_fail(effp->handler.usage);
                         return (SOX_EOF);
                 }
                 i++;
@@ -136,7 +134,7 @@
 /*
  * Prepare for processing.
  */
-static int sox_chorus_start(eff_t effp)
+static int sox_chorus_start(sox_effect_t effp)
 {
         chorus_t chorus = (chorus_t) effp->priv;
         int i;
@@ -243,7 +241,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_chorus_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_chorus_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                    sox_size_t *isamp, sox_size_t *osamp)
 {
         chorus_t chorus = (chorus_t) effp->priv;
@@ -281,7 +279,7 @@
 /*
  * Drain out reverb lines. 
  */
-static int sox_chorus_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_chorus_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         chorus_t chorus = (chorus_t) effp->priv;
         sox_size_t done;
@@ -324,7 +322,7 @@
 /*
  * Clean up chorus effect.
  */
-static int sox_chorus_stop(eff_t effp)
+static int sox_chorus_stop(sox_effect_t effp)
 {
         chorus_t chorus = (chorus_t) effp->priv;
         int i;
@@ -338,7 +336,7 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_chorus_effect = {
+static sox_effect_handler_t sox_chorus_effect = {
   "chorus",
   "Usage: chorus gain-in gain-out delay decay speed depth [ -s | -t ]",
   SOX_EFF_LENGTH,
@@ -347,10 +345,10 @@
   sox_chorus_flow,
   sox_chorus_drain,
   sox_chorus_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_chorus_effect_fn(void)
+const sox_effect_handler_t *sox_chorus_effect_fn(void)
 {
     return &sox_chorus_effect;
 }
--- a/src/compand.c
+++ b/src/compand.c
@@ -59,7 +59,7 @@
   int delay_buf_full;       /* Shows buffer situation (important for drain) */
 } * compand_t;
 
-static int getopts(eff_t effp, int n, char * * argv)
+static int getopts(sox_effect_t effp, int n, char * * argv)
 {
   compand_t l = (compand_t) effp->priv;
   char * s;
@@ -67,7 +67,7 @@
   unsigned pairs, i, j, commas;
 
   if (n < 2 || n > 5) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
 
@@ -126,7 +126,7 @@
   return SOX_SUCCESS;
 }
 
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
   compand_t l = (compand_t) effp->priv;
   unsigned i, j;
@@ -175,7 +175,7 @@
     *v += delta * l->channels[chan].attack_times[1];
 }
 
-static int flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
+static int flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
                     sox_size_t *isamp, sox_size_t *osamp)
 {
   compand_t l = (compand_t) effp->priv;
@@ -236,7 +236,7 @@
   return (SOX_SUCCESS);
 }
 
-static int drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   compand_t l = (compand_t) effp->priv;
   sox_size_t chan, done = 0;
@@ -256,7 +256,7 @@
   return l->delay_buf_cnt > 0 ? SOX_SUCCESS : SOX_EOF;
 }
 
-static int stop(eff_t effp)
+static int stop(sox_effect_t effp)
 {
   compand_t l = (compand_t) effp->priv;
 
@@ -264,7 +264,7 @@
   return SOX_SUCCESS;
 }
 
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
   compand_t l = (compand_t) effp->priv;
 
@@ -273,11 +273,11 @@
   return SOX_SUCCESS;
 }
 
-sox_effect_t const * sox_compand_effect_fn(void)
+sox_effect_handler_t const * sox_compand_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "compand", compand_usage, SOX_EFF_MCHAN,
     getopts, start, flow, drain, stop, kill
   };
-  return &driver;
+  return &handler;
 }
--- a/src/dcshift.c
+++ b/src/dcshift.c
@@ -15,8 +15,6 @@
 
 #include <math.h>   /* exp(), sqrt() */
 
-static sox_effect_t sox_dcshift_effect;
-
 typedef struct {
     double dcshift; /* DC shift. */
     int uselimiter; /* boolean: are we using the limiter? */
@@ -30,7 +28,7 @@
 /*
  * Process options: dcshift (double) type (amplitude, power, dB)
  */
-static int sox_dcshift_getopts(eff_t effp, int n, char **argv)
+static int sox_dcshift_getopts(sox_effect_t effp, int n, char **argv)
 {
     dcs_t dcs = (dcs_t) effp->priv;
     dcs->dcshift = 1.0; /* default is no change */
@@ -38,13 +36,13 @@
 
     if (n < 1)
     {
-        sox_fail(sox_dcshift_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
     if (n && (!sscanf(argv[0], "%lf", &dcs->dcshift)))
     {
-        sox_fail(sox_dcshift_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
@@ -52,7 +50,7 @@
     {
         if (!sscanf(argv[1], "%lf", &dcs->limitergain))
         {
-                sox_fail(sox_dcshift_effect.usage);
+                sox_fail(effp->handler.usage);
                 return SOX_EOF;
         }
 
@@ -72,7 +70,7 @@
 /*
  * Start processing
  */
-static int sox_dcshift_start(eff_t effp)
+static int sox_dcshift_start(sox_effect_t effp)
 {
     dcs_t dcs = (dcs_t) effp->priv;
 
@@ -101,7 +99,7 @@
 /*
  * Process data.
  */
-static int sox_dcshift_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_dcshift_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                     sox_size_t *isamp, sox_size_t *osamp)
 {
     dcs_t dcs = (dcs_t) effp->priv;
@@ -168,7 +166,7 @@
  * Do anything required when you stop reading samples.
  * Don't close input file!
  */
-static int sox_dcshift_stop(eff_t effp)
+static int sox_dcshift_stop(sox_effect_t effp)
 {
     dcs_t dcs = (dcs_t) effp->priv;
 
@@ -193,7 +191,7 @@
     return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_dcshift_effect = {
+static sox_effect_handler_t sox_dcshift_effect = {
    "dcshift",
    "Usage: dcshift shift [ limitergain ]\n"
    "       The peak limiter has a gain much less than 1.0 (ie 0.05 or 0.02) which is only\n"
@@ -202,12 +200,12 @@
    sox_dcshift_getopts,
    sox_dcshift_start,
    sox_dcshift_flow,
-   sox_effect_nothing_drain,
+   NULL,
    sox_dcshift_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_dcshift_effect_fn(void)
+const sox_effect_handler_t *sox_dcshift_effect_fn(void)
 {
     return &sox_dcshift_effect;
 }
--- a/src/dither.c
+++ b/src/dither.c
@@ -23,12 +23,12 @@
 assert_static(sizeof(struct dither) <= SOX_MAX_EFFECT_PRIVSIZE,
               /* else */ dither_PRIVSIZE_too_big);
 
-static int getopts(eff_t effp, int n, char * * argv)
+static int getopts(sox_effect_t effp, int n, char * * argv)
 {
   dither_t dither = (dither_t) effp->priv;
 
   if (n > 1) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   
@@ -40,7 +40,7 @@
     if (scanned == 1 && amount > 0)
       dither->amount *= amount;
     else {
-      sox_fail(effp->h->usage);
+      sox_fail(effp->handler.usage);
       return SOX_EOF;
     }
   }
@@ -48,7 +48,7 @@
   return SOX_SUCCESS;
 }
 
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
   dither_t dither = (dither_t) effp->priv;
 
@@ -65,7 +65,7 @@
   return SOX_EFF_NULL;   /* Dithering not needed at >= 24 bits */
 }
 
-static int flow(eff_t effp, const sox_ssample_t * ibuf,
+static int flow(sox_effect_t effp, const sox_ssample_t * ibuf,
     sox_ssample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
   dither_t dither = (dither_t)effp->priv;
@@ -80,20 +80,20 @@
   return SOX_SUCCESS;
 }
 
-sox_effect_t const * sox_dither_effect_fn(void)
+sox_effect_handler_t const * sox_dither_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "dither", "Usage: dither [amount]", SOX_EFF_MCHAN,
     getopts, start, flow, 0, 0, 0
   };
-  return &driver;
+  return &handler;
 }
 
-sox_effect_t const * sox_mask_effect_fn(void)
+sox_effect_handler_t const * sox_mask_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "mask", "Usage: mask [amount]", SOX_EFF_MCHAN | SOX_EFF_DEPRECATED,
     getopts, start, flow, 0, 0, 0
   };
-  return &driver;
+  return &handler;
 }
--- a/src/earwax.c
+++ b/src/earwax.c
@@ -24,8 +24,6 @@
 
 #include "sox_i.h"
 
-static sox_effect_t sox_earwax_effect;
-
 #define EARWAX_SCALE 64
 
 /* A stereo fir filter. One side filters as if the signal was from
@@ -75,7 +73,7 @@
 /*
  * Prepare for processing.
  */
-static int sox_earwax_start(eff_t effp)
+static int sox_earwax_start(sox_effect_t effp)
 {
   earwax_t earwax = (earwax_t) effp->priv;
   int i;
@@ -102,7 +100,7 @@
  * Return number of samples processed.
  */
 
-static int sox_earwax_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_earwax_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                    sox_size_t *isamp, sox_size_t *osamp)
 {
   earwax_t earwax = (earwax_t) effp->priv;
@@ -134,7 +132,7 @@
 /*
  * Drain out taps.
  */
-static int sox_earwax_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_earwax_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   earwax_t earwax = (earwax_t) effp->priv;
   int i,j;
@@ -155,7 +153,7 @@
 /*
  * Clean up taps.
  */
-static int sox_earwax_stop(eff_t effp)
+static int sox_earwax_stop(sox_effect_t effp)
 {
   earwax_t earwax = (earwax_t) effp->priv;
 
@@ -164,19 +162,19 @@
   return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_earwax_effect = {
+static sox_effect_handler_t sox_earwax_effect = {
   "earwax",
   "Usage: The earwax filtering effect takes no options",
   SOX_EFF_MCHAN|SOX_EFF_LENGTH,
-  sox_effect_nothing_getopts,
+  NULL,
   sox_earwax_start,
   sox_earwax_flow,
   sox_earwax_drain,
   sox_earwax_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_earwax_effect_fn(void)
+const sox_effect_handler_t *sox_earwax_effect_fn(void)
 {
     return &sox_earwax_effect;
 }
--- a/src/echo.c
+++ b/src/echo.c
@@ -59,8 +59,6 @@
 #include <math.h>
 #include "sox_i.h"
 
-static sox_effect_t sox_echo_effect;
-
 #define DELAY_BUFSIZ ( 50 * SOX_MAXRATE )
 #define MAX_ECHOS 7     /* 24 bit x ( 1 + MAX_ECHOS ) = */
                         /* 24 bit x 8 = 32 bit !!!      */
@@ -82,7 +80,7 @@
 /*
  * Process options
  */
-static int sox_echo_getopts(eff_t effp, int n, char **argv) 
+static int sox_echo_getopts(sox_effect_t effp, int n, char **argv) 
 {
         echo_t echo = (echo_t) effp->priv;
         int i;
@@ -91,7 +89,7 @@
 
         if ((n < 4) || (n % 2))
         {
-            sox_fail(sox_echo_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
 
@@ -113,7 +111,7 @@
 /*
  * Prepare for processing.
  */
-static int sox_echo_start(eff_t effp)
+static int sox_echo_start(sox_effect_t effp)
 {
         echo_t echo = (echo_t) effp->priv;
         int i;
@@ -180,7 +178,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_echo_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_echo_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                  sox_size_t *isamp, sox_size_t *osamp)
 {
         echo_t echo = (echo_t) effp->priv;
@@ -216,7 +214,7 @@
 /*
  * Drain out reverb lines. 
  */
-static int sox_echo_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_echo_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         echo_t echo = (echo_t) effp->priv;
         double d_in, d_out;
@@ -256,7 +254,7 @@
 /*
  * Clean up reverb effect.
  */
-static int sox_echo_stop(eff_t effp)
+static int sox_echo_stop(sox_effect_t effp)
 {
         echo_t echo = (echo_t) effp->priv;
 
@@ -265,7 +263,7 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_echo_effect = {
+static sox_effect_handler_t sox_echo_effect = {
   "echo",
   "Usage: echo gain-in gain-out delay decay [ delay decay ... ]",
   SOX_EFF_LENGTH,
@@ -274,10 +272,10 @@
   sox_echo_flow,
   sox_echo_drain,
   sox_echo_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_echo_effect_fn(void)
+const sox_effect_handler_t *sox_echo_effect_fn(void)
 {
     return &sox_echo_effect;
 }
--- a/src/echos.c
+++ b/src/echos.c
@@ -50,8 +50,6 @@
 #include <math.h>
 #include "sox_i.h"
 
-static sox_effect_t sox_echos_effect;
-
 #define DELAY_BUFSIZ ( 50 * SOX_MAXRATE )
 #define MAX_ECHOS 7     /* 24 bit x ( 1 + MAX_ECHOS ) = */
                         /* 24 bit x 8 = 32 bit !!!      */
@@ -72,7 +70,7 @@
 /*
  * Process options
  */
-static int sox_echos_getopts(eff_t effp, int n, char **argv) 
+static int sox_echos_getopts(sox_effect_t effp, int n, char **argv) 
 {
         echos_t echos = (echos_t) effp->priv;
         int i;
@@ -81,7 +79,7 @@
 
         if ((n < 4) || (n % 2))
         {
-            sox_fail(sox_echos_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
 
@@ -107,7 +105,7 @@
 /*
  * Prepare for processing.
  */
-static int sox_echos_start(eff_t effp)
+static int sox_echos_start(sox_effect_t effp)
 {
         echos_t echos = (echos_t) effp->priv;
         int i;
@@ -172,7 +170,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_echos_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_echos_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                 sox_size_t *isamp, sox_size_t *osamp)
 {
         echos_t echos = (echos_t) effp->priv;
@@ -214,7 +212,7 @@
 /*
  * Drain out reverb lines. 
  */
-static int sox_echos_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_echos_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         echos_t echos = (echos_t) effp->priv;
         double d_in, d_out;
@@ -260,7 +258,7 @@
 /*
  * Clean up echos effect.
  */
-static int sox_echos_stop(eff_t effp)
+static int sox_echos_stop(sox_effect_t effp)
 {
         echos_t echos = (echos_t) effp->priv;
 
@@ -269,7 +267,7 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_echos_effect = {
+static sox_effect_handler_t sox_echos_effect = {
   "echos",
   "Usage: echos gain-in gain-out delay decay [ delay decay ... ]",
   SOX_EFF_LENGTH,
@@ -278,10 +276,10 @@
   sox_echos_flow,
   sox_echos_drain,
   sox_echos_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_echos_effect_fn(void)
+const sox_effect_handler_t *sox_echos_effect_fn(void)
 {
     return &sox_echos_effect;
 }
--- a/src/effects.c
+++ b/src/effects.c
@@ -18,26 +18,30 @@
 
 #include "sox_i.h"
 
-struct sox_effect * effects[MAX_EFFECTS];
-unsigned neffects;
+sox_effect_t sox_effects[SOX_MAX_EFFECTS];
+unsigned sox_neffects;
 
 
-void add_effect(struct sox_effect * e, sox_signalinfo_t * in, sox_signalinfo_t * out, int * effects_mask)
+int sox_add_effect(sox_effect_t e, sox_signalinfo_t * in, sox_signalinfo_t * out, int * effects_mask)
 {
   unsigned f, flows;
 
-  *effects_mask = sox_updateeffect(e, in, out, *effects_mask);
+  if (sox_neffects == SOX_MAX_EFFECTS)
+    return SOX_EOF;
 
-  flows = (e->h->flags & SOX_EFF_MCHAN)? 1 : e->ininfo.channels;
+  *effects_mask = sox_update_effect(e, in, out, *effects_mask);
 
-  effects[neffects] = xcalloc(flows, sizeof(effects[neffects][0]));
-  effects[neffects][0] = *e;
-  effects[neffects][0].flows = flows;
+  flows = (e->handler.flags & SOX_EFF_MCHAN)? 1 : e->ininfo.channels;
 
+  sox_effects[sox_neffects] = xcalloc(flows, sizeof(sox_effects[sox_neffects][0]));
+  sox_effects[sox_neffects][0] = *e;
+  sox_effects[sox_neffects][0].flows = flows;
+
   for (f = 1; f < flows; ++f)
-    effects[neffects][f] = effects[neffects][0];
+    sox_effects[sox_neffects][f] = sox_effects[sox_neffects][0];
 
-  ++neffects;
+  ++sox_neffects;
+  return SOX_SUCCESS;
 }
 
 static void stop_effect(unsigned e)
@@ -45,77 +49,72 @@
   unsigned i;
 
   sox_size_t clips = 0;
-  int (*stop)(eff_t effp) =
-     effects[e][0].h->stop? effects[e][0].h->stop : sox_effect_nothing;
 
-  for (i = 0; i < effects[e][0].flows; ++i) {
-    stop(&effects[e][i]);
-    clips += effects[e][i].clips;
+  for (i = 0; i < sox_effects[e][0].flows; ++i) {
+    sox_effects[e][0].handler.stop(&sox_effects[e][i]);
+    clips += sox_effects[e][i].clips;
   }
   if (clips != 0)
-    sox_warn("'%s' clipped %u samples; decrease volume?",effects[e][0].name,clips);
+    sox_warn("'%s' clipped %u samples; decrease volume?",sox_effects[e][0].handler.name,clips);
 }
 
-void stop_effects(void)
+void sox_stop_effects(void)
 {
   unsigned e;
-  for (e = 0; e < neffects; ++e)
+  for (e = 0; e < sox_neffects; ++e)
     stop_effect(e);
 }
 
 static void kill_effect(unsigned e)
 {
-  int (*kill)(eff_t effp) =
-     effects[e][0].h->kill? effects[e][0].h->kill : sox_effect_nothing;
-
-  kill(&effects[e][0]);  /* One kill for all flows */
+  sox_effects[e][0].handler.kill(&sox_effects[e][0]);/* One kill for all flows */
 }
 
-void kill_effects(void)
+void sox_kill_effects(void)
 {
   unsigned e;
-  for (e = 0; e < neffects; ++e)
+  for (e = 0; e < sox_neffects; ++e)
     kill_effect(e);
 }
 
-int start_effects(void)
+int sox_start_effects(void)
 {
   unsigned i, j;
   int ret = SOX_SUCCESS;
 
-  for (i = 0; i < neffects; ++i) {
-    struct sox_effect * e = &effects[i][0];
-    sox_bool is_always_null = (e->h->flags & SOX_EFF_NULL) != 0;
-    int (*start)(eff_t effp) = e->h->start? e->h->start : sox_effect_nothing;
+  for (i = 0; i < sox_neffects; ++i) {
+    sox_effect_t e = &sox_effects[i][0];
+    sox_bool is_always_null = (e->handler.flags & SOX_EFF_NULL) != 0;
+    int (*start)(sox_effect_t effp) = e->handler.start;
 
     if (is_always_null)
-      sox_report("'%s' has no effect (is a proxy effect)", e->name);
+      sox_report("'%s' has no effect (is a proxy effect)", e->handler.name);
     else {
       e->clips = 0;
       ret = start(e);
       if (ret == SOX_EFF_NULL)
-        sox_warn("'%s' has no effect in this configuration", e->name);
+        sox_warn("'%s' has no effect in this configuration", e->handler.name);
       else if (ret != SOX_SUCCESS)
         return SOX_EOF;
     }
     if (is_always_null || ret == SOX_EFF_NULL) { /* remove from the chain */
       kill_effect(i);
-      free(effects[i]);
-      --neffects;
-      for (j = i--; j < neffects; ++j)
-        effects[j] = effects[j + 1];
+      free(sox_effects[i]);
+      --sox_neffects;
+      for (j = i--; j < sox_neffects; ++j)
+        sox_effects[j] = sox_effects[j + 1];
     }
-    else for (j = 1; j < effects[i][0].flows; ++j) {
-      effects[i][j].clips = 0;
-      if (start(&effects[i][j]) != SOX_SUCCESS)
+    else for (j = 1; j < sox_effects[i][0].flows; ++j) {
+      sox_effects[i][j].clips = 0;
+      if (start(&sox_effects[i][j]) != SOX_SUCCESS)
         return SOX_EOF;
     }
   }
-  for (i = 0; i < neffects; ++i) {
-    struct sox_effect * e = &effects[i][0];
+  for (i = 0; i < sox_neffects; ++i) {
+    sox_effect_t e = &sox_effects[i][0];
     sox_report("Effects chain: %-10s %uHz %u channels %s",
-        e->name, e->ininfo.rate, e->ininfo.channels,
-        (e->h->flags & SOX_EFF_MCHAN)? "(multi)" : "");
+        e->handler.name, e->ininfo.rate, e->ininfo.channels,
+        (e->handler.flags & SOX_EFF_MCHAN)? "(multi)" : "");
   }
   return SOX_SUCCESS;
 }
@@ -124,35 +123,32 @@
 
 static int flow_effect(unsigned e)
 {
-  sox_size_t i, f, idone, odone;
-  const sox_ssample_t *ibuf;
   int effstatus = SOX_SUCCESS;
-  int (*flow)(eff_t, sox_ssample_t const*, sox_ssample_t*, sox_size_t*, sox_size_t*) =
-    effects[e][0].h->flow? effects[e][0].h->flow : sox_effect_nothing_flow;
+  sox_size_t i, f;
+  const sox_ssample_t *ibuf;
+  sox_size_t idone = sox_effects[e - 1][0].olen - sox_effects[e - 1][0].odone;
+  sox_size_t odone = sox_bufsiz - sox_effects[e][0].olen;
 
-  idone = effects[e - 1][0].olen - effects[e - 1][0].odone;
-  odone = sox_bufsiz - effects[e][0].olen;
-
-  if (effects[e][0].flows == 1)   /* Run effect on all channels at once */
-    effstatus = flow(&effects[e][0],
-      &effects[e - 1][0].obuf[effects[e - 1][0].odone],
-      &effects[e][0].obuf[effects[e][0].olen], &idone, &odone);
+  if (sox_effects[e][0].flows == 1)   /* Run effect on all channels at once */
+    effstatus = sox_effects[e][0].handler.flow(&sox_effects[e][0],
+      &sox_effects[e - 1][0].obuf[sox_effects[e - 1][0].odone],
+      &sox_effects[e][0].obuf[sox_effects[e][0].olen], &idone, &odone);
   else {                         /* Run effect on each channel individually */
-    sox_ssample_t *obuf = &effects[e][0].obuf[effects[e][0].olen];
+    sox_ssample_t *obuf = &sox_effects[e][0].obuf[sox_effects[e][0].olen];
     sox_size_t idone_last, odone_last;
 
-    ibuf = &effects[e - 1][0].obuf[effects[e - 1][0].odone];
-    for (i = 0; i < idone; i += effects[e][0].flows)
-      for (f = 0; f < effects[e][0].flows; ++f)
-        ibufc[f][i / effects[e][0].flows] = *ibuf++;
+    ibuf = &sox_effects[e - 1][0].obuf[sox_effects[e - 1][0].odone];
+    for (i = 0; i < idone; i += sox_effects[e][0].flows)
+      for (f = 0; f < sox_effects[e][0].flows; ++f)
+        ibufc[f][i / sox_effects[e][0].flows] = *ibuf++;
 
-    for (f = 0; f < effects[e][0].flows; ++f) {
-      sox_size_t idonec = idone / effects[e][0].flows;
-      sox_size_t odonec = odone / effects[e][0].flows;
-      int eff_status_c =
-        flow(&effects[e][f], ibufc[f], obufc[f], &idonec, &odonec);
+    for (f = 0; f < sox_effects[e][0].flows; ++f) {
+      sox_size_t idonec = idone / sox_effects[e][0].flows;
+      sox_size_t odonec = odone / sox_effects[e][0].flows;
+      int eff_status_c = sox_effects[e][0].handler.flow(&sox_effects[e][f],
+          ibufc[f], obufc[f], &idonec, &odonec);
       if (f && (idonec != idone_last || odonec != odone_last)) {
-        sox_fail("'%s' flowed asymmetrically!", effects[e][0].name);
+        sox_fail("'%s' flowed asymmetrically!", sox_effects[e][0].handler.name);
         effstatus = SOX_EOF;
       }
       idone_last = idonec;
@@ -163,43 +159,41 @@
     }
 
     for (i = 0; i < odone_last; ++i)
-      for (f = 0; f < effects[e][0].flows; ++f)
+      for (f = 0; f < sox_effects[e][0].flows; ++f)
         *obuf++ = obufc[f][i];
 
     idone = f * idone_last;
     odone = f * odone_last;
   }
-  effects[e - 1][0].odone += idone;
-  if (effects[e - 1][0].odone == effects[e - 1][0].olen) /* Can reuse this buffer? */
-    effects[e - 1][0].odone = effects[e - 1][0].olen = 0;
+  sox_effects[e - 1][0].odone += idone;
+  if (sox_effects[e - 1][0].odone == sox_effects[e - 1][0].olen) /* Can reuse this buffer? */
+    sox_effects[e - 1][0].odone = sox_effects[e - 1][0].olen = 0;
 
-  effects[e][0].olen += odone;
+  sox_effects[e][0].olen += odone;
 
   return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF;
 }
 
+/* The same as flow_effect but with no input */
 static int drain_effect(unsigned e)
 {
-  sox_size_t i, f, odone;
   int effstatus = SOX_SUCCESS;
-  int (*drain)(eff_t, sox_ssample_t*, sox_size_t*) =
-    effects[e][0].h->drain? effects[e][0].h->drain : sox_effect_nothing_drain;
+  sox_size_t i, f;
+  sox_size_t odone = sox_bufsiz - sox_effects[e][0].olen;
 
-  odone = sox_bufsiz - effects[e][0].olen;
-
-  if (effects[e][0].flows == 1)   /* Run effect on all channels at once */
-    effstatus = drain(&effects[e][0],
-      &effects[e][0].obuf[effects[e][0].olen], &odone);
+  if (sox_effects[e][0].flows == 1)   /* Run effect on all channels at once */
+    effstatus = sox_effects[e][0].handler.drain(&sox_effects[e][0],
+      &sox_effects[e][0].obuf[sox_effects[e][0].olen], &odone);
   else {                         /* Run effect on each channel individually */
-    sox_ssample_t *obuf = &effects[e][0].obuf[effects[e][0].olen];
+    sox_ssample_t *obuf = &sox_effects[e][0].obuf[sox_effects[e][0].olen];
     sox_size_t odone_last;
 
-    for (f = 0; f < effects[e][0].flows; ++f) {
-      sox_size_t odonec = odone / effects[e][0].flows;
+    for (f = 0; f < sox_effects[e][0].flows; ++f) {
+      sox_size_t odonec = odone / sox_effects[e][0].flows;
       int eff_status_c =
-        drain(&effects[e][f], obufc[f], &odonec);
+        sox_effects[e][0].handler.drain(&sox_effects[e][f], obufc[f], &odonec);
       if (f && (odonec != odone_last)) {
-        sox_fail("'%s' drained asymmetrically!", effects[e][0].name);
+        sox_fail("'%s' drained asymmetrically!", sox_effects[e][0].handler.name);
         effstatus = SOX_EOF;
       }
       odone_last = odonec;
@@ -209,19 +203,19 @@
     }
 
     for (i = 0; i < odone_last; ++i)
-      for (f = 0; f < effects[e][0].flows; ++f)
+      for (f = 0; f < sox_effects[e][0].flows; ++f)
         *obuf++ = obufc[f][i];
     odone = f * odone_last;
   }
-  if (!odone)
+  if (!odone)   /* This is the only thing that drain has and flow hasn't */
     effstatus = SOX_EOF;
 
-  effects[e][0].olen += odone;
+  sox_effects[e][0].olen += odone;
 
   return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF;
 }
 
-int flow_effects(void (* update_status)(sox_bool), sox_bool * user_abort)
+int sox_flow_effects(void (* update_status)(sox_bool), sox_bool * user_abort)
 {
   int e, source_e = 0;               /* effect indices */
   int flow_status = SOX_SUCCESS;
@@ -228,10 +222,10 @@
   sox_bool draining = sox_true;
   sox_size_t f, max_flows = 0;
 
-  for (e = 0; e < (int)neffects; ++e) {
-    effects[e][0].obuf = xmalloc(sox_bufsiz * sizeof(effects[e][0].obuf[0]));
-    effects[e][0].odone = effects[e][0].olen = 0;
-    max_flows = max(max_flows, effects[e][0].flows);
+  for (e = 0; e < (int)sox_neffects; ++e) {
+    sox_effects[e][0].obuf = xmalloc(sox_bufsiz * sizeof(sox_effects[e][0].obuf[0]));
+    sox_effects[e][0].odone = sox_effects[e][0].olen = 0;
+    max_flows = max(max_flows, sox_effects[e][0].flows);
   }
 
   ibufc = xcalloc(max_flows, sizeof(*ibufc));
@@ -242,8 +236,8 @@
   }
 
   --e;
-  while (source_e < (int)neffects) {
-    if (e == source_e && (draining || effects[e - 1][0].odone == effects[e - 1][0].olen)) {
+  while (source_e < (int)sox_neffects) {
+    if (e == source_e && (draining || sox_effects[e - 1][0].odone == sox_effects[e - 1][0].olen)) {
       if (drain_effect(e) == SOX_EOF) {
         ++source_e;
         draining = sox_false;
@@ -253,12 +247,12 @@
       source_e = e;
       draining = sox_true;
     }
-    if (effects[e][0].odone < effects[e][0].olen)
+    if (sox_effects[e][0].odone < sox_effects[e][0].olen)
       ++e;
     else if (--e < source_e)
       e = source_e;
 
-    update_status(*user_abort || source_e == (int)neffects);
+    update_status(*user_abort || source_e == (int)sox_neffects);
     
     if (*user_abort) /* Don't get stuck in this loop. */
       return SOX_EOF;
@@ -271,14 +265,14 @@
   free(obufc);
   free(ibufc);
 
-  for (e = 0; e < (int)neffects; ++e)
-    free(effects[e][0].obuf);
+  for (e = 0; e < (int)sox_neffects; ++e)
+    free(sox_effects[e][0].obuf);
 
   return flow_status;
 }
 
-void delete_effects(void)
+void sox_delete_effects(void)
 {
-  while (neffects)
-    free(effects[--neffects]);
+  while (sox_neffects)
+    free(sox_effects[--sox_neffects]);
 }
--- a/src/fade.c
+++ b/src/fade.c
@@ -23,8 +23,6 @@
 #include <string.h>
 #include "sox_i.h"
 
-static sox_effect_t sox_fade_effect;
-
 /* Private data for fade file */
 typedef struct fadestuff
 { /* These are measured as samples */
@@ -45,7 +43,7 @@
  * The 'info' fields are not yet filled in.
  */
 
-static int sox_fade_getopts(eff_t effp, int n, char **argv)
+static int sox_fade_getopts(sox_effect_t effp, int n, char **argv)
 {
 
     fade_t fade = (fade_t) effp->priv;
@@ -54,7 +52,7 @@
 
     if (n < 1 || n > 4)
     { /* Wrong number of arguments. */
-        sox_fail(sox_fade_effect.usage);
+        sox_fail(effp->handler.usage);
         return(SOX_EOF);
     }
 
@@ -82,7 +80,7 @@
     /* Do a dummy parse to see if it will fail */
     if (sox_parsesamples(0, fade->in_stop_str, &fade->in_stop, 't') == NULL)
     {
-        sox_fail(sox_fade_effect.usage);
+        sox_fail(effp->handler.usage);
         return(SOX_EOF);
     }
 
@@ -99,7 +97,7 @@
             /* Do a dummy parse to see if it will fail */
             if (sox_parsesamples(0, fade->out_stop_str, 
                                 &fade->out_stop, 't') == NULL) {
-              sox_fail(sox_fade_effect.usage);
+              sox_fail(effp->handler.usage);
               return(SOX_EOF);
             }
         }
@@ -111,7 +109,7 @@
             /* Do a dummy parse to see if it will fail */
             if (sox_parsesamples(0, fade->out_start_str, 
                                 &fade->out_start, 't') == NULL) {
-              sox_fail(sox_fade_effect.usage);
+              sox_fail(effp->handler.usage);
               return(SOX_EOF);
             }
         }
@@ -124,7 +122,7 @@
  * Prepare processing.
  * Do all initializations.
  */
-static int sox_fade_start(eff_t effp)
+static int sox_fade_start(sox_effect_t effp)
 {
     fade_t fade = (fade_t) effp->priv;
 
@@ -133,7 +131,7 @@
     if (sox_parsesamples(effp->ininfo.rate, fade->in_stop_str,
                         &fade->in_stop, 't') == NULL)
     {
-        sox_fail(sox_fade_effect.usage);
+        sox_fail(effp->handler.usage);
         return(SOX_EOF);
     }
 
@@ -145,7 +143,7 @@
         if (sox_parsesamples(effp->ininfo.rate, fade->out_stop_str,
                             &fade->out_stop, 't') == NULL)
         {
-            sox_fail(sox_fade_effect.usage);
+            sox_fail(effp->handler.usage);
             return(SOX_EOF);
         }
 
@@ -155,7 +153,7 @@
             if (sox_parsesamples(effp->ininfo.rate, fade->out_start_str,
                         &fade->out_start, 't') == NULL)
             {
-                sox_fail(sox_fade_effect.usage);
+                sox_fail(effp->handler.usage);
                 return(SOX_EOF);
             }
             /* Fade time is relative to stop time. */
@@ -197,7 +195,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_fade_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_fade_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                  sox_size_t *isamp, sox_size_t *osamp)
 {
     fade_t fade = (fade_t) effp->priv;
@@ -278,7 +276,7 @@
 /*
  * Drain out remaining samples if the effect generates any.
  */
-static int sox_fade_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_fade_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
     fade_t fade = (fade_t) effp->priv;
     int len;
@@ -319,7 +317,7 @@
  * Do anything required when you stop reading samples.
  *      (free allocated memory, etc.)
  */
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
     fade_t fade = (fade_t) effp->priv;
 
@@ -371,7 +369,7 @@
     return retval;
 }
 
-static sox_effect_t sox_fade_effect = {
+static sox_effect_handler_t sox_fade_effect = {
   "fade",
   "Usage: fade [ type ] fade-in-length [ stop-time [ fade-out-length ] ]\n"
   "       Time is in hh:mm:ss.frac format.\n"
@@ -381,11 +379,11 @@
   sox_fade_start,
   sox_fade_flow,
   sox_fade_drain,
-  sox_effect_nothing,
+  NULL,
   kill
 };
 
-const sox_effect_t *sox_fade_effect_fn(void)
+const sox_effect_handler_t *sox_fade_effect_fn(void)
 {
     return &sox_fade_effect;
 }
--- a/src/filter.c
+++ b/src/filter.c
@@ -27,8 +27,6 @@
 
 #include "sox_i.h"
 
-static sox_effect_t sox_filter_effect;
-
 #define ISCALE 0x10000
 #define BUFFSIZE 8192
 
@@ -54,7 +52,7 @@
 /*
  * Process options
  */
-static int sox_filter_getopts(eff_t effp, int n, char **argv)
+static int sox_filter_getopts(sox_effect_t effp, int n, char **argv)
 {
         filter_t f = (filter_t) effp->priv;
 
@@ -77,13 +75,13 @@
         sox_debug("freq: %d-%d", f->freq0, f->freq1);
         if (f->freq0 == 0 && f->freq1 == 0)
         {
-                sox_fail(sox_filter_effect.usage);
+                sox_fail(effp->handler.usage);
                 return (SOX_EOF);
         }
 
         if ((n >= 2) && !sscanf(argv[1], "%ld", &f->Nwin))
         {
-                sox_fail(sox_filter_effect.usage);
+                sox_fail(effp->handler.usage);
                 return (SOX_EOF);
         }
         else if (f->Nwin < 4) {
@@ -93,7 +91,7 @@
 
         if ((n >= 3) && !sscanf(argv[2], "%lf", &f->beta))
         {
-                sox_fail(sox_filter_effect.usage);
+                sox_fail(effp->handler.usage);
                 return (SOX_EOF);
         }
 
@@ -104,7 +102,7 @@
 /*
  * Prepare processing.
  */
-static int sox_filter_start(eff_t effp)
+static int sox_filter_start(sox_effect_t effp)
 {
         filter_t f = (filter_t) effp->priv;
         double *Fp0, *Fp1;
@@ -182,7 +180,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_filter_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_filter_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                    sox_size_t *isamp, sox_size_t *osamp)
 {
         filter_t f = (filter_t) effp->priv;
@@ -235,7 +233,7 @@
 /*
  * Process tail of input samples.
  */
-static int sox_filter_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_filter_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         filter_t f = (filter_t) effp->priv;
         long isamp_res, osamp_res;
@@ -272,7 +270,7 @@
  * Do anything required when you stop reading samples.  
  * Don't close input file! 
  */
-static int sox_filter_stop(eff_t effp)
+static int sox_filter_stop(sox_effect_t effp)
 {
         filter_t f = (filter_t) effp->priv;
 
@@ -311,7 +309,7 @@
         }
 }
 
-static sox_effect_t sox_filter_effect = {
+static sox_effect_handler_t sox_filter_effect = {
   "filter",
   "Usage: filter low-high [ windowlength [ beta ] ]",
   0,
@@ -320,10 +318,10 @@
   sox_filter_flow,
   sox_filter_drain,
   sox_filter_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_filter_effect_fn(void)
+const sox_effect_handler_t *sox_filter_effect_fn(void)
 {
     return &sox_filter_effect;
 }
--- a/src/flac.c
+++ b/src/flac.c
@@ -522,11 +522,11 @@
 const sox_format_t *sox_flac_format_fn(void)
 {
   static char const * const names[] = {"flac", NULL};
-  static sox_format_t const driver = {
+  static sox_format_t handler = {
     names, SOX_FILE_SEEK,
     start_read, read, stop_read,
     start_write, write, stop_write,
     seek
   };
-  return &driver;
+  return &handler;
 }
--- a/src/flanger.c
+++ b/src/flanger.c
@@ -110,7 +110,7 @@
   d = strtod(*argv, &end_ptr); \
   if (end_ptr != *argv) { \
     if (d < min || d > max || *end_ptr != '\0') { \
-      sox_fail(effp->h->usage); \
+      sox_fail(effp->handler.usage); \
       return SOX_EOF; \
     } \
     f->p = d; \
@@ -132,7 +132,7 @@
 
 
 
-static int sox_flanger_getopts(eff_t effp, int argc, char *argv[])
+static int sox_flanger_getopts(sox_effect_t effp, int argc, char *argv[])
 {
   flanger_t f = (flanger_t) effp->priv;
 
@@ -154,7 +154,7 @@
   } while (0);
 
   if (argc != 0) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
 
@@ -181,7 +181,7 @@
 
 
 
-static int sox_flanger_start(eff_t effp)
+static int sox_flanger_start(sox_effect_t effp)
 {
   flanger_t f = (flanger_t) effp->priv;
   int c, channels = effp->ininfo.channels;
@@ -234,7 +234,7 @@
 
 
 
-static int sox_flanger_flow(eff_t effp, sox_ssample_t const * ibuf,
+static int sox_flanger_flow(sox_effect_t effp, sox_ssample_t const * ibuf,
     sox_ssample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
   flanger_t f = (flanger_t) effp->priv;
@@ -289,7 +289,7 @@
 
 
 
-static int sox_flanger_stop(eff_t effp)
+static int sox_flanger_stop(sox_effect_t effp)
 {
   flanger_t f = (flanger_t) effp->priv;
   int c, channels = effp->ininfo.channels;
@@ -306,7 +306,7 @@
 
 
 
-static sox_effect_t sox_flanger_effect = {
+static sox_effect_handler_t sox_flanger_effect = {
   "flanger",
   sox_flanger_usage,
   SOX_EFF_MCHAN,
@@ -313,14 +313,14 @@
   sox_flanger_getopts,
   sox_flanger_start,
   sox_flanger_flow,
-  sox_effect_nothing_drain,
+  NULL,
   sox_flanger_stop,
-  sox_effect_nothing
+  NULL
 };
 
 
 
-sox_effect_t const * sox_flanger_effect_fn(void)
+sox_effect_handler_t const * sox_flanger_effect_fn(void)
 {
   return &sox_flanger_effect;
 }
--- a/src/ima-fmt.c
+++ b/src/ima-fmt.c
@@ -18,7 +18,7 @@
 const sox_format_t *sox_ima_format_fn(void)
 {
   static char const * names[] = {"ima", NULL};
-  static sox_format_t driver = {
+  static sox_format_t handler = {
     names, 0,
     sox_ima_start,
     sox_vox_read,
@@ -28,5 +28,5 @@
     sox_vox_stopwrite,
     sox_format_nothing_seek
   };
-  return &driver;
+  return &handler;
 }
--- a/src/maud.c
+++ b/src/maud.c
@@ -1,5 +1,5 @@
 /*
- * libSoX MAUD file format driver, by Lutz Vieweg 1993
+ * libSoX MAUD file format handler, by Lutz Vieweg 1993
  *
  * supports: mono and stereo, linear, a-law and u-law reading and writing
  *
--- a/src/mcompand.c
+++ b/src/mcompand.c
@@ -123,7 +123,7 @@
   return (SOX_SUCCESS);
 }
 
-static int lowpass_flow(eff_t effp, butterworth_crossover_t butterworth, sox_size_t nChan, sox_ssample_t *ibuf, sox_ssample_t *lowbuf, sox_ssample_t *highbuf,
+static int lowpass_flow(sox_effect_t effp, butterworth_crossover_t butterworth, sox_size_t nChan, sox_ssample_t *ibuf, sox_ssample_t *lowbuf, sox_ssample_t *highbuf,
                          sox_size_t len) {
   sox_size_t chan;
   double in, out;
@@ -300,7 +300,7 @@
       return SOX_SUCCESS;
 }
 
-static int sox_mcompand_getopts(eff_t effp, int n, char **argv) 
+static int sox_mcompand_getopts(sox_effect_t effp, int n, char **argv) 
 {
   char *subargv[6], *cp;
   sox_size_t subargc, i, len;
@@ -348,7 +348,7 @@
  * Prepare processing.
  * Do all initializations.
  */
-static int sox_mcompand_start(eff_t effp)
+static int sox_mcompand_start(sox_effect_t effp)
 {
   compand_t c = (compand_t) effp->priv;
   comp_band_t l;
@@ -407,7 +407,7 @@
     *v += delta * l->decayRate[chan];
 }
 
-static int sox_mcompand_flow_1(eff_t effp, compand_t c, comp_band_t l, const sox_ssample_t *ibuf, sox_ssample_t *obuf, sox_size_t len, sox_size_t filechans)
+static int sox_mcompand_flow_1(sox_effect_t effp, compand_t c, comp_band_t l, const sox_ssample_t *ibuf, sox_ssample_t *obuf, sox_size_t len, sox_size_t filechans)
 {
   sox_size_t done, chan;
 
@@ -477,7 +477,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_mcompand_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_mcompand_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                      sox_size_t *isamp, sox_size_t *osamp) {
   compand_t c = (compand_t) effp->priv;
   comp_band_t l;
@@ -529,7 +529,7 @@
   return SOX_SUCCESS;
 }
 
-static int sox_mcompand_drain_1(eff_t effp, compand_t c, comp_band_t l, sox_ssample_t *obuf, sox_size_t maxdrain)
+static int sox_mcompand_drain_1(sox_effect_t effp, compand_t c, comp_band_t l, sox_ssample_t *obuf, sox_size_t maxdrain)
 {
   sox_size_t done;
   double out;
@@ -553,7 +553,7 @@
 /*
  * Drain out compander delay lines. 
  */
-static int sox_mcompand_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_mcompand_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   sox_size_t band, drained, mostdrained = 0;
   compand_t c = (compand_t)effp->priv;
@@ -578,7 +578,7 @@
 /*
  * Clean up compander effect.
  */
-static int sox_mcompand_stop(eff_t effp)
+static int sox_mcompand_stop(sox_effect_t effp)
 {
   compand_t c = (compand_t) effp->priv;
   comp_band_t l;
@@ -603,7 +603,7 @@
   return SOX_SUCCESS;
 }
 
-static int sox_mcompand_kill(eff_t effp)
+static int sox_mcompand_kill(sox_effect_t effp)
 {
   compand_t c = (compand_t) effp->priv;
   comp_band_t l;
@@ -622,7 +622,7 @@
   return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_mcompand_effect = {
+static sox_effect_handler_t sox_mcompand_effect = {
   "mcompand",
   "Usage: mcompand quoted_compand_args [crossover_frequency quoted_compand_args [...]]\n"
   "\n"
@@ -640,7 +640,7 @@
   sox_mcompand_kill
 };
 
-const sox_effect_t *sox_mcompand_effect_fn(void)
+const sox_effect_handler_t *sox_mcompand_effect_fn(void)
 {
     return &sox_mcompand_effect;
 }
--- a/src/misc.c
+++ b/src/misc.c
@@ -313,37 +313,6 @@
 sox_size_t sox_format_nothing_write(ft_t ft UNUSED, const sox_ssample_t *buf UNUSED, sox_size_t len UNUSED) { return(0); }
 int sox_format_nothing_seek(ft_t ft UNUSED, sox_size_t offset UNUSED) { sox_fail_errno(ft, SOX_ENOTSUP, "operation not supported"); return(SOX_EOF); }
 
-/* dummy effect routine for do-nothing functions */
-int sox_effect_nothing(eff_t effp UNUSED)
-{
-  return SOX_SUCCESS;
-}
-
-int sox_effect_nothing_flow(eff_t effp UNUSED, const sox_ssample_t *ibuf UNUSED, sox_ssample_t *obuf UNUSED, sox_size_t *isamp, sox_size_t *osamp)
-{
-  /* Pass through samples verbatim */
-  *isamp = *osamp = min(*isamp, *osamp);
-  memcpy(obuf, ibuf, *isamp * sizeof(sox_ssample_t));
-  return SOX_SUCCESS;
-}
-
-int sox_effect_nothing_drain(eff_t effp UNUSED, sox_ssample_t *obuf UNUSED, sox_size_t *osamp)
-{
-  /* Inform no more samples to drain */
-  *osamp = 0;
-  return SOX_EOF;
-}
-
-int sox_effect_nothing_getopts(eff_t effp, int n, char **argv UNUSED)
-{
-  if (n) {
-    sox_fail(effp->h->usage);
-    return (SOX_EOF);
-  }
-  return (SOX_SUCCESS);
-}
-
-
 /* here for linear interp.  might be useful for other things */
 sox_ssample_t sox_gcd(sox_ssample_t a, sox_ssample_t b)
 {
--- a/src/mixer.c
+++ b/src/mixer.c
@@ -20,8 +20,6 @@
 #include <string.h>
 #include <stdlib.h>
 
-static sox_effect_t sox_mixer_effect;
-
 typedef struct mixerstuff {
         /* How to generate each output channel.  sources[i][j] */
         /* represents the fraction of channel i that should be passed */
@@ -49,7 +47,7 @@
 /*
  * Process options
  */
-static int getopts(eff_t effp, int n, char **argv) 
+static int getopts(sox_effect_t effp, int n, char **argv) 
 {
     mixer_t mixer = (mixer_t) effp->priv;
     double* pans = &mixer->sources[0][0];
@@ -82,7 +80,7 @@
             mixer->mix = MIX_RIGHT_BACK;
         else if (argv[0][0] == '-' && !isdigit((int)argv[0][1])
                 && argv[0][1] != '.') {
-            sox_fail(sox_mixer_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
         else {
@@ -107,7 +105,7 @@
         mixer->mix = MIX_CENTER;
     }
     else {
-        sox_fail(sox_mixer_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
@@ -117,7 +115,7 @@
 /*
  * Start processing
  */
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
     /*
        Hmmm, this is tricky.  Lemme think:
@@ -510,7 +508,7 @@
  * Process either isamp or osamp samples, whichever is smaller.
  */
 
-static int flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                 sox_size_t *isamp, sox_size_t *osamp)
 {
     mixer_t mixer = (mixer_t) effp->priv;
@@ -538,35 +536,35 @@
     return (SOX_SUCCESS);
 }
 
-sox_effect_t const * sox_mixer_effect_fn(void)
+sox_effect_handler_t const * sox_mixer_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "mixer",
     "Usage: mixer [ -l | -r | -f | -b | -1 | -2 | -3 | -4 | n,n,n...,n ]",
     SOX_EFF_MCHAN | SOX_EFF_CHAN,
     getopts, start, flow, 0, 0, 0
   };
-  return &driver;
+  return &handler;
 }
 
-sox_effect_t const * sox_avg_effect_fn(void)
+sox_effect_handler_t const * sox_avg_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "avg",
     "Usage: avg [ -l | -r | -f | -b | -1 | -2 | -3 | -4 | n,n,n...,n ]",
     SOX_EFF_MCHAN | SOX_EFF_CHAN | SOX_EFF_DEPRECATED,
     getopts, start, flow, 0, 0, 0
   };
-  return &driver;
+  return &handler;
 }
 
-sox_effect_t const * sox_pick_effect_fn(void)
+sox_effect_handler_t const * sox_pick_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "pick",
     "Usage: pick [ -l | -r | -f | -b | -1 | -2 | -3 | -4 | n,n,n...,n ]",
     SOX_EFF_MCHAN | SOX_EFF_CHAN | SOX_EFF_DEPRECATED,
     getopts, start, flow, 0, 0, 0
   };
-  return &driver;
+  return &handler;
 }
--- a/src/noiseprof.c
+++ b/src/noiseprof.c
@@ -19,8 +19,6 @@
 #include <string.h>
 #include <errno.h>
 
-static sox_effect_t sox_noiseprof_effect;
-
 typedef struct chandata {
     float *sum;
     int   *profilecount;
@@ -39,7 +37,7 @@
 /*
  * Get the filename, if any. We don't open it until sox_noiseprof_start.
  */
-static int sox_noiseprof_getopts(eff_t effp, int n, char **argv) 
+static int sox_noiseprof_getopts(sox_effect_t effp, int n, char **argv) 
 {
     profdata_t data = (profdata_t) effp->priv;
 
@@ -46,7 +44,7 @@
     if (n == 1) {
         data->output_filename = argv[0];
     } else if (n > 1) {
-        sox_fail(sox_noiseprof_effect.usage);
+        sox_fail(effp->handler.usage);
         return (SOX_EOF);
     }
 
@@ -57,7 +55,7 @@
  * Prepare processing.
  * Do all initializations.
  */
-static int sox_noiseprof_start(eff_t effp)
+static int sox_noiseprof_start(sox_effect_t effp)
 {
   profdata_t data = (profdata_t) effp->priv;
   unsigned channels = effp->ininfo.channels;
@@ -70,7 +68,7 @@
       sox_fail("stdout already in use by '%s'", effp->global_info->global_info->stdout_in_use_by);
       return SOX_EOF;
     }
-    effp->global_info->global_info->stdout_in_use_by = effp->name;
+    effp->global_info->global_info->stdout_in_use_by = effp->handler.name;
     data->output_file = stdout;
   }
   else if ((data->output_file = fopen(data->output_filename, "w")) == NULL) {
@@ -110,7 +108,7 @@
 /*
  * Grab what we can from ibuf, and process if we have a whole window.
  */
-static int sox_noiseprof_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_noiseprof_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                     sox_size_t *isamp, sox_size_t *osamp)
 {
     profdata_t data = (profdata_t) effp->priv;
@@ -152,7 +150,7 @@
  * Finish off the last window.
  */
 
-static int sox_noiseprof_drain(eff_t effp, sox_ssample_t *obuf UNUSED, sox_size_t *osamp)
+static int sox_noiseprof_drain(sox_effect_t effp, sox_ssample_t *obuf UNUSED, sox_size_t *osamp)
 {
     profdata_t data = (profdata_t) effp->priv;
     int tracks = effp->ininfo.channels;
@@ -181,7 +179,7 @@
 /*
  * Print profile and clean up.
  */
-static int sox_noiseprof_stop(eff_t effp)
+static int sox_noiseprof_stop(sox_effect_t effp)
 {
     profdata_t data = (profdata_t) effp->priv;
     sox_size_t i;
@@ -211,7 +209,7 @@
     return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_noiseprof_effect = {
+static sox_effect_handler_t sox_noiseprof_effect = {
   "noiseprof",
   "Usage: noiseprof [profile-file]",
   SOX_EFF_MCHAN,
@@ -220,10 +218,10 @@
   sox_noiseprof_flow,
   sox_noiseprof_drain,
   sox_noiseprof_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_noiseprof_effect_fn(void)
+const sox_effect_handler_t *sox_noiseprof_effect_fn(void)
 {
     return &sox_noiseprof_effect;
 }
--- a/src/noisered.c
+++ b/src/noisered.c
@@ -23,7 +23,7 @@
   d = strtod(*argv, &end_ptr); \
   if (end_ptr != *argv) { \
     if (d < min || d > max || *end_ptr != '\0') { \
-      sox_fail(effp->h->usage); \
+      sox_fail(effp->handler.usage); \
       return SOX_EOF; \
     } \
     this->p = d; \
@@ -31,8 +31,6 @@
   } \
 }
 
-static sox_effect_t sox_noisered_effect;
-
 typedef struct chandata {
     float *window;
     float *lastwindow;
@@ -53,7 +51,7 @@
  * Get the options. Default file is stdin (if the audio
  * input file isn't coming from there, of course!)
  */
-static int sox_noisered_getopts(eff_t effp, int argc, char **argv)
+static int sox_noisered_getopts(sox_effect_t effp, int argc, char **argv)
 {
   reddata_t this = (reddata_t) effp->priv;
 
@@ -69,7 +67,7 @@
   } while (0);
 
   if (argc != 0) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   return SOX_SUCCESS;
@@ -79,7 +77,7 @@
  * Prepare processing.
  * Do all initializations.
  */
-static int sox_noisered_start(eff_t effp)
+static int sox_noisered_start(sox_effect_t effp)
 {
     reddata_t data = (reddata_t) effp->priv;
     sox_size_t fchannels = 0;
@@ -101,7 +99,7 @@
         sox_fail("stdin already in use by '%s'", effp->global_info->global_info->stdin_in_use_by);
         return SOX_EOF;
       }
-      effp->global_info->global_info->stdin_in_use_by = effp->name;
+      effp->global_info->global_info->stdin_in_use_by = effp->handler.name;
       ifp = stdin;
     }
     else if ((ifp = fopen(data->profile_filename, "r")) == NULL) {
@@ -221,7 +219,7 @@
 
 /* Do window management once we have a complete window, including mangling
  * the current window. */
-static int process_window(eff_t effp, reddata_t data, unsigned chan_num, unsigned num_chans,
+static int process_window(sox_effect_t effp, reddata_t data, unsigned chan_num, unsigned num_chans,
                           sox_ssample_t *obuf, unsigned len) {
     int j;
     float* nextwindow;
@@ -259,7 +257,7 @@
 /*
  * Read in windows, and call process_window once we get a whole one.
  */
-static int sox_noisered_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_noisered_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                     sox_size_t *isamp, sox_size_t *osamp)
 {
     reddata_t data = (reddata_t) effp->priv;
@@ -309,7 +307,7 @@
  * We have up to half a window left to dump.
  */
 
-static int sox_noisered_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_noisered_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
     reddata_t data = (reddata_t)effp->priv;
     unsigned i;
@@ -326,7 +324,7 @@
 /*
  * Clean up.
  */
-static int sox_noisered_stop(eff_t effp)
+static int sox_noisered_stop(sox_effect_t effp)
 {
     reddata_t data = (reddata_t) effp->priv;
     sox_size_t i;
@@ -344,7 +342,7 @@
     return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_noisered_effect = {
+static sox_effect_handler_t sox_noisered_effect = {
   "noisered",
   "Usage: noisered [profile-file [amount]]",
   SOX_EFF_MCHAN|SOX_EFF_LENGTH,
@@ -353,10 +351,10 @@
   sox_noisered_flow,
   sox_noisered_drain,
   sox_noisered_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_noisered_effect_fn(void)
+const sox_effect_handler_t *sox_noisered_effect_fn(void)
 {
     return &sox_noisered_effect;
 }
--- a/src/nulfile.c
+++ b/src/nulfile.c
@@ -57,9 +57,9 @@
 const sox_format_t *sox_nul_format_fn(void)
 {
   static const char *names[] = { "null", "nul"/* with -t; deprecated*/, NULL};
-  static sox_format_t driver = {
+  static sox_format_t handler = {
     names, SOX_FILE_DEVICE | SOX_FILE_PHONY | SOX_FILE_NOSTDIO,
     startread, read, 0, 0, write, 0, 0
   };
-  return &driver;
+  return &handler;
 }
--- a/src/pad.c
+++ b/src/pad.c
@@ -35,7 +35,7 @@
 assert_static(sizeof(struct pad) <= SOX_MAX_EFFECT_PRIVSIZE,
               /* else */ pad_PRIVSIZE_too_big);
 
-static int parse(eff_t effp, char * * argv, sox_rate_t rate)
+static int parse(sox_effect_t effp, char * * argv, sox_rate_t rate)
 {
   pad_t p = (pad_t) effp->priv;
   char const * next;
@@ -56,13 +56,13 @@
     if (i > 0 && p->pads[i].start <= p->pads[i-1].start) break;
   }
   if (i < p->npads) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   return SOX_SUCCESS;
 }
 
-static int create(eff_t effp, int n, char * * argv)
+static int create(sox_effect_t effp, int n, char * * argv)
 {
   pad_t p = (pad_t) effp->priv;
   p->pads = xcalloc(p->npads = n, sizeof(*p->pads));
@@ -69,7 +69,7 @@
   return parse(effp, argv, SOX_MAXRATE); /* No rate yet; parse with dummy */
 }
 
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
   pad_t p = (pad_t) effp->priv;
   unsigned i;
@@ -82,7 +82,7 @@
   return SOX_EFF_NULL;
 }
 
-static int flow(eff_t effp, const sox_ssample_t * ibuf, sox_ssample_t * obuf,
+static int flow(sox_effect_t effp, const sox_ssample_t * ibuf, sox_ssample_t * obuf,
                 sox_size_t * isamp, sox_size_t * osamp)
 {
   pad_t p = (pad_t) effp->priv;
@@ -111,7 +111,7 @@
   return SOX_SUCCESS;
 }
 
-static int drain(eff_t effp, sox_ssample_t * obuf, sox_size_t * osamp)
+static int drain(sox_effect_t effp, sox_ssample_t * obuf, sox_size_t * osamp)
 {
   static sox_size_t isamp = 0;
   pad_t p = (pad_t) effp->priv;
@@ -120,7 +120,7 @@
   return flow(effp, 0, obuf, &isamp, osamp);
 }
 
-static int stop(eff_t effp)
+static int stop(sox_effect_t effp)
 {
   pad_t p = (pad_t) effp->priv;
   if (p->pads_pos != p->npads)
@@ -128,7 +128,7 @@
   return SOX_SUCCESS;
 }
 
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
   pad_t p = (pad_t) effp->priv;
   unsigned i;
@@ -138,11 +138,11 @@
   return SOX_SUCCESS;
 }
 
-sox_effect_t const * sox_pad_effect_fn(void)
+sox_effect_handler_t const * sox_pad_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "pad", "Usage: pad {length[@position]}", SOX_EFF_MCHAN|SOX_EFF_LENGTH,
     create, start, flow, drain, stop, kill
   };
-  return &driver;
+  return &handler;
 }
--- a/src/pan.c
+++ b/src/pan.c
@@ -19,8 +19,6 @@
 #include "sox_i.h"
 #include <string.h>
 
-static sox_effect_t sox_pan_effect;
-
 /* structure to hold pan parameter */
 
 typedef struct {
@@ -30,7 +28,7 @@
 /*
  * Process options
  */
-static int sox_pan_getopts(eff_t effp, int n, char **argv) 
+static int sox_pan_getopts(sox_effect_t effp, int n, char **argv) 
 {
     pan_t pan = (pan_t) effp->priv; 
     
@@ -39,7 +37,7 @@
     if (n && (!sscanf(argv[0], "%lf", &pan->dir) || 
               pan->dir < -1.0 || pan->dir > 1.0))
     {
-        sox_fail(sox_pan_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
@@ -49,7 +47,7 @@
 /*
  * Start processing
  */
-static int sox_pan_start(eff_t effp)
+static int sox_pan_start(sox_effect_t effp)
 {
     if (effp->outinfo.channels==1)
         sox_warn("PAN onto a mono channel...");
@@ -73,7 +71,7 @@
 /*
  * Process either isamp or osamp samples, whichever is smaller.
  */
-static int sox_pan_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_pan_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                 sox_size_t *isamp, sox_size_t *osamp)
 {
     pan_t pan = (pan_t) effp->priv;
@@ -411,7 +409,7 @@
  * FIXME: Add a stop function with statistics on right, left, and output amplitudes.
  */
 
-static sox_effect_t sox_pan_effect = {
+static sox_effect_handler_t sox_pan_effect = {
   "pan",
   "Usage: pan direction (in [-1.0 .. 1.0])",
   SOX_EFF_MCHAN | SOX_EFF_CHAN,
@@ -418,12 +416,12 @@
   sox_pan_getopts,
   sox_pan_start,
   sox_pan_flow,
-  sox_effect_nothing_drain,
-  sox_effect_nothing,
-  sox_effect_nothing
+  NULL,
+  NULL,
+  NULL
 };
 
-const sox_effect_t *sox_pan_effect_fn(void)
+const sox_effect_handler_t *sox_pan_effect_fn(void)
 {
     return &sox_pan_effect;
 }
--- a/src/phaser.c
+++ b/src/phaser.c
@@ -59,8 +59,6 @@
 #include <string.h>
 #include "sox_i.h"
 
-static sox_effect_t sox_phaser_effect;
-
 #define MOD_SINE        0
 #define MOD_TRIANGLE    1
 
@@ -81,13 +79,13 @@
 /*
  * Process options
  */
-static int sox_phaser_getopts(eff_t effp, int n, char **argv) 
+static int sox_phaser_getopts(sox_effect_t effp, int n, char **argv) 
 {
         phaser_t phaser = (phaser_t) effp->priv;
 
         if (!((n == 5) || (n == 6)))
         {
-            sox_fail(sox_phaser_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
 
@@ -104,7 +102,7 @@
                         phaser->modulation = MOD_TRIANGLE;
                 else
                 {
-                        sox_fail(sox_phaser_effect.usage);
+                        sox_fail(effp->handler.usage);
                         return (SOX_EOF);
                 }
         }
@@ -114,7 +112,7 @@
 /*
  * Prepare for processing.
  */
-static int sox_phaser_start(eff_t effp)
+static int sox_phaser_start(sox_effect_t effp)
 {
         phaser_t phaser = (phaser_t) effp->priv;
         unsigned int i;
@@ -179,7 +177,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_phaser_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_phaser_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                    sox_size_t *isamp, sox_size_t *osamp)
 {
         phaser_t phaser = (phaser_t) effp->priv;
@@ -213,7 +211,7 @@
 /*
  * Drain out reverb lines. 
  */
-static int sox_phaser_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_phaser_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         phaser_t phaser = (phaser_t) effp->priv;
         sox_size_t done;
@@ -252,7 +250,7 @@
 /*
  * Clean up phaser effect.
  */
-static int sox_phaser_stop(eff_t effp)
+static int sox_phaser_stop(sox_effect_t effp)
 {
         phaser_t phaser = (phaser_t) effp->priv;
 
@@ -261,7 +259,7 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_phaser_effect = {
+static sox_effect_handler_t sox_phaser_effect = {
   "phaser",
   "Usage: phaser gain-in gain-out delay decay speed [ -s | -t ]",
   SOX_EFF_LENGTH,
@@ -270,10 +268,10 @@
   sox_phaser_flow,
   sox_phaser_drain,
   sox_phaser_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_phaser_effect_fn(void)
+const sox_effect_handler_t *sox_phaser_effect_fn(void)
 {
     return &sox_phaser_effect;
 }
--- a/src/pitch.c
+++ b/src/pitch.c
@@ -42,8 +42,6 @@
 
 #include <math.h>   /* cos(), pow() */
 
-static sox_effect_t sox_pitch_effect;
-
 /* cross fading options for transitions
  */
 #define PITCH_FADE_COS 0 /* cosine */
@@ -246,7 +244,7 @@
 /*
  * Process options
  */
-static int sox_pitch_getopts(eff_t effp, int n, char **argv) 
+static int sox_pitch_getopts(sox_effect_t effp, int n, char **argv) 
 {
     pitch_t pitch = (pitch_t) effp->priv; 
     
@@ -255,7 +253,7 @@
 
     if (n && !sscanf(argv[0], "%lf", &pitch->shift))
     {
-        sox_fail(sox_pitch_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
@@ -263,7 +261,7 @@
     pitch->width = PITCH_DEFAULT_WIDTH;
     if (n>1 && !sscanf(argv[1], "%lf", &pitch->width))
     {
-        sox_fail(sox_pitch_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
@@ -282,7 +280,7 @@
             pitch->interopt = PITCH_INTERPOLE_CUB;
             break;
         default:
-            sox_fail(sox_pitch_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
     }
@@ -310,7 +308,7 @@
             pitch->fadeopt = PITCH_FADE_COS;
             break;
         default:
-            sox_fail(sox_pitch_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
     }
@@ -319,7 +317,7 @@
     if (n>4 && (!sscanf(argv[4], "%lf", &pitch->coef) ||
                 pitch->coef<0.0 || pitch->coef>0.5))
     {
-        sox_fail(sox_pitch_effect.usage);
+        sox_fail(effp->handler.usage);
         return SOX_EOF;
     }
 
@@ -329,7 +327,7 @@
 /*
  * Start processing
  */
-static int sox_pitch_start(eff_t effp)
+static int sox_pitch_start(sox_effect_t effp)
 {
     pitch_t pitch = (pitch_t) effp->priv;
     register int sample_rate = effp->outinfo.rate;
@@ -441,7 +439,7 @@
 
 /* Processes input.
  */
-static int sox_pitch_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_pitch_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                 sox_size_t *isamp, sox_size_t *osamp)
 {
     pitch_t pitch = (pitch_t) effp->priv;
@@ -518,7 +516,7 @@
 
 /* at the end...
  */
-static int sox_pitch_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_pitch_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
     pitch_t pitch = (pitch_t) effp->priv;
     sox_size_t i;
@@ -562,7 +560,7 @@
  * Do anything required when you stop reading samples.  
  * Don't close input file! 
  */
-static int sox_pitch_stop(eff_t effp)
+static int sox_pitch_stop(sox_effect_t effp)
 {
     pitch_t pitch = (pitch_t) effp->priv;
 
@@ -574,7 +572,7 @@
     return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_pitch_effect = {
+static sox_effect_handler_t sox_pitch_effect = {
   "pitch",
   "Usage: pitch shift width interpole fade\n"
   "       (in cents, in ms, cub/lin, cos/ham/lin/trap)"
@@ -585,10 +583,10 @@
   sox_pitch_flow,
   sox_pitch_drain,
   sox_pitch_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_pitch_effect_fn(void)
+const sox_effect_handler_t *sox_pitch_effect_fn(void)
 {
     return &sox_pitch_effect;
 }
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -63,7 +63,7 @@
 /*
  * Process options
  */
-static int sox_poly_getopts(eff_t effp, int n, char **argv)
+static int sox_poly_getopts(sox_effect_t effp, int n, char **argv)
 {
   poly_t rate = (poly_t) effp->priv;
 
@@ -340,7 +340,7 @@
 
 #define RIBLEN 2048
 
-static int sox_poly_start(eff_t effp)
+static int sox_poly_start(sox_effect_t effp)
 {
     poly_t rate = (poly_t) effp->priv;
     static int l1[MF], l2[MF];
@@ -488,7 +488,7 @@
 
 }
 
-static int sox_poly_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
+static int sox_poly_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
                  sox_size_t *isamp, sox_size_t *osamp)
 {
   poly_t rate = (poly_t) effp->priv;
@@ -591,7 +591,7 @@
 /*
  * Process tail of input samples.
  */
-static int sox_poly_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_poly_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   sox_size_t in_size;
   /* Call "flow" with NULL input. */
@@ -603,7 +603,7 @@
  * Do anything required when you stop reading samples.
  * Don't close input file!
  */
-static int sox_poly_stop(eff_t effp)
+static int sox_poly_stop(sox_effect_t effp)
 {
     poly_t rate = (poly_t)effp->priv;
     sox_size_t k;
@@ -617,7 +617,7 @@
     return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_polyphase_effect = {
+static sox_effect_handler_t sox_polyphase_effect = {
   "polyphase",
   "Usage: -w {nut|ham}   window type\n"
   "       -width n       window width in samples [default 1024]\n"
@@ -629,10 +629,10 @@
   sox_poly_flow,
   sox_poly_drain,
   sox_poly_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_polyphase_effect_fn(void)
+const sox_effect_handler_t *sox_polyphase_effect_fn(void)
 {
     return &sox_polyphase_effect;
 }
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -32,8 +32,6 @@
 #include <math.h>
 #include <samplerate.h>
 
-static sox_effect_t sox_rabbit_effect;
-
 /* Private data for resampling */
 typedef struct {
   int converter_type;           /* SRC converter type */
@@ -46,7 +44,7 @@
 /*
  * Process options
  */
-static int sox_rabbit_getopts(eff_t effp, int n, char **argv)
+static int sox_rabbit_getopts(sox_effect_t effp, int n, char **argv)
 {
   rabbit_t r = (rabbit_t) effp->priv;
 
@@ -72,7 +70,7 @@
   }
 
   if (n >= 1) {
-    sox_fail(sox_rabbit_effect.usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
 
@@ -82,7 +80,7 @@
 /*
  * Prepare processing.
  */
-static int sox_rabbit_start(eff_t effp)
+static int sox_rabbit_start(sox_effect_t effp)
 {
   rabbit_t r = (rabbit_t) effp->priv;
 
@@ -111,7 +109,7 @@
 /*
  * Read all the data.
  */
-static int sox_rabbit_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf UNUSED,
+static int sox_rabbit_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf UNUSED,
                    sox_size_t *isamp, sox_size_t *osamp)
 {
   rabbit_t r = (rabbit_t) effp->priv;
@@ -141,7 +139,7 @@
 /*
  * Process samples and write output.
  */
-static int sox_rabbit_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_rabbit_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   rabbit_t r = (rabbit_t) effp->priv;
   int channels = effp->ininfo.channels;
@@ -186,7 +184,7 @@
  * Do anything required when you stop reading samples.
  * Don't close input file!
  */
-static int sox_rabbit_stop(eff_t effp)
+static int sox_rabbit_stop(sox_effect_t effp)
 {
   rabbit_t r = (rabbit_t) effp->priv;
 
@@ -195,7 +193,7 @@
   return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_rabbit_effect = {
+static sox_effect_handler_t sox_rabbit_effect = {
   "rabbit",
   "Usage: rabbit [-c0|-c1|-c2|-c3|-c4]",
   SOX_EFF_RATE | SOX_EFF_MCHAN,
@@ -204,10 +202,10 @@
   sox_rabbit_flow,
   sox_rabbit_drain,
   sox_rabbit_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_rabbit_effect_fn(void)
+const sox_effect_handler_t *sox_rabbit_effect_fn(void)
 {
   return &sox_rabbit_effect;
 }
--- a/src/rate.c
+++ b/src/rate.c
@@ -7,14 +7,14 @@
 
 #include "sox_i.h"
  
-int sox_resample_getopts(eff_t effp, int n, char **argv);
-int sox_resample_start(eff_t effp);
-int sox_resample_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+int sox_resample_getopts(sox_effect_t effp, int n, char **argv);
+int sox_resample_start(sox_effect_t effp);
+int sox_resample_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                      sox_size_t *isamp, sox_size_t *osamp);
-int sox_resample_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
-int sox_resample_stop(eff_t effp);
+int sox_resample_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
+int sox_resample_stop(sox_effect_t effp);
 
-static sox_effect_t sox_rate_effect = {
+static sox_effect_handler_t sox_rate_effect = {
   "rate",
   "Usage: Rate effect takes no options",
   SOX_EFF_RATE | SOX_EFF_DEPRECATED,
@@ -23,10 +23,10 @@
   sox_resample_flow,
   sox_resample_drain,
   sox_resample_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_rate_effect_fn(void)
+const sox_effect_handler_t *sox_rate_effect_fn(void)
 {
     return &sox_rate_effect;
 }
--- a/src/raw-fmt.c
+++ b/src/raw-fmt.c
@@ -19,11 +19,11 @@
 const sox_format_t *sox_raw_format_fn(void)
 {
   static char const * names[] = {"raw", NULL};
-  static sox_format_t driver = {
+  static sox_format_t handler = {
     names, SOX_FILE_SEEK,
     raw_start, sox_rawread , sox_format_nothing,
     raw_start, sox_rawwrite, sox_format_nothing,
     sox_rawseek
   };
-  return &driver;
+  return &handler;
 }
--- a/src/raw.h
+++ b/src/raw.h
@@ -15,13 +15,13 @@
 } \
 const sox_format_t *sox_ ## id ## _format_fn(void); \
 const sox_format_t *sox_ ## id ## _format_fn(void) { \
-  static sox_format_t driver = { \
+  static sox_format_t handler = { \
     names, flags, \
     id ## _start, sox_rawread , sox_format_nothing, \
     id ## _start, sox_rawwrite, sox_format_nothing, \
     sox_format_nothing_seek \
   }; \
-  return &driver; \
+  return &handler; \
 }
 
 #define RAW_FORMAT(id, size, flags, encoding) \
--- a/src/repeat.c
+++ b/src/repeat.c
@@ -24,8 +24,6 @@
 #include <string.h>
 #include <sys/types.h> /* for off_t on OS/2 and possibly others */
 
-static sox_effect_t sox_repeat_effect;
-
 typedef struct repeatstuff {
         FILE *fp;
         int first_drain;
@@ -34,12 +32,12 @@
         int repeats;
 } *repeat_t;
 
-static int sox_repeat_getopts(eff_t effp, int n, char **argv)
+static int sox_repeat_getopts(sox_effect_t effp, int n, char **argv)
 {
         repeat_t repeat = (repeat_t)effp->priv;
 
         if (n != 1) {
-                sox_fail(sox_repeat_effect.usage);
+                sox_fail(effp->handler.usage);
                 return (SOX_EOF);
         }
 
@@ -56,7 +54,7 @@
         return (SOX_SUCCESS);
 }
 
-static int sox_repeat_start(eff_t effp)
+static int sox_repeat_start(sox_effect_t effp)
 {
         repeat_t repeat = (repeat_t)effp->priv;
 
@@ -73,7 +71,7 @@
         return (SOX_SUCCESS);
 }
 
-static int sox_repeat_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf UNUSED,
+static int sox_repeat_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf UNUSED,
                 sox_size_t *isamp, sox_size_t *osamp)
 {
         repeat_t repeat = (repeat_t)effp->priv;
@@ -89,7 +87,7 @@
         return (SOX_SUCCESS);
 }
 
-static int sox_repeat_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_repeat_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         size_t read = 0;
         sox_ssample_t *buf;
@@ -187,7 +185,7 @@
             return SOX_SUCCESS;
 }
 
-static int sox_repeat_stop(eff_t effp)
+static int sox_repeat_stop(sox_effect_t effp)
 {
         repeat_t repeat = (repeat_t)effp->priv;
 
@@ -196,7 +194,7 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_repeat_effect = {
+static sox_effect_handler_t sox_repeat_effect = {
   "repeat",
   "Usage: repeat count",
   SOX_EFF_MCHAN | SOX_EFF_LENGTH,
@@ -205,10 +203,10 @@
   sox_repeat_flow,
   sox_repeat_drain,
   sox_repeat_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_repeat_effect_fn(void)
+const sox_effect_handler_t *sox_repeat_effect_fn(void)
 {
     return &sox_repeat_effect;
 }
--- a/src/resample.c
+++ b/src/resample.c
@@ -86,8 +86,6 @@
  *
  */
 
-static sox_effect_t sox_resample_effect;
-
 #define ISCALE 0x10000
 
 /* largest factor for which exact-coefficients upsampling will be used */
@@ -141,7 +139,7 @@
 /*
  * Process options
  */
-int sox_resample_getopts(eff_t effp, int n, char **argv)
+int sox_resample_getopts(sox_effect_t effp, int n, char **argv)
 {
         resample_t r = (resample_t) effp->priv;
 
@@ -171,7 +169,7 @@
         }
 
         if ((n >= 1) && (sscanf(argv[0], "%lf", &r->rolloff) != 1)) {
-          sox_fail(sox_resample_effect.usage);
+          sox_fail(effp->handler.usage);
           return (SOX_EOF);
         } else if ((r->rolloff <= 0.01) || (r->rolloff >= 1.0)) {
           sox_fail("resample: rolloff factor (%f) no good, should be 0.01<x<1.0", r->rolloff);
@@ -179,7 +177,7 @@
         }
 
         if ((n >= 2) && !sscanf(argv[1], "%lf", &r->beta)) {
-        	sox_fail(sox_resample_effect.usage);
+        	sox_fail(effp->handler.usage);
           	return (SOX_EOF);
         } else if (r->beta <= 2.0) {
         	r->beta = 0;
@@ -192,7 +190,7 @@
 /*
  * Prepare processing.
  */
-int sox_resample_start(eff_t effp)
+int sox_resample_start(sox_effect_t effp)
 {
   resample_t r = (resample_t) effp->priv;
   long Xoff, gcdrate;
@@ -280,7 +278,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-int sox_resample_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+int sox_resample_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                      sox_size_t *isamp, sox_size_t *osamp)
 {
         resample_t r = (resample_t) effp->priv;
@@ -385,7 +383,7 @@
 /*
  * Process tail of input samples.
  */
-int sox_resample_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+int sox_resample_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         resample_t r = (resample_t) effp->priv;
         long isamp_res, osamp_res;
@@ -425,7 +423,7 @@
  * Do anything required when you stop reading samples.  
  * Don't close input file! 
  */
-int sox_resample_stop(eff_t effp)
+int sox_resample_stop(sox_effect_t effp)
 {
         resample_t r = (resample_t) effp->priv;
         
@@ -723,7 +721,7 @@
    }
 }
 
-static sox_effect_t sox_resample_effect = {
+static sox_effect_handler_t sox_resample_effect = {
    "resample",
    "Usage: resample [ -qs | -q | -ql ] [ rolloff [ beta ] ]",
    SOX_EFF_RATE,
@@ -732,10 +730,10 @@
    sox_resample_flow,
    sox_resample_drain,
    sox_resample_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_resample_effect_fn(void)
+const sox_effect_handler_t *sox_resample_effect_fn(void)
 {
     return &sox_resample_effect;
 }
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -95,8 +95,6 @@
 #include <math.h>
 #include "sox_i.h"
 
-static sox_effect_t sox_reverb_effect;
-
 #define REVERB_FADE_THRESH 10
 #define DELAY_BUFSIZ ( 50 * SOX_MAXRATE )
 #define MAXREVERBS 8
@@ -115,7 +113,7 @@
 /*
  * Process options
  */
-static int sox_reverb_getopts(eff_t effp, int n, char **argv) 
+static int sox_reverb_getopts(sox_effect_t effp, int n, char **argv) 
 {
         reverb_t reverb = (reverb_t) effp->priv;
         int i;
@@ -125,7 +123,7 @@
 
         if ( n < 3 )
         {
-            sox_fail(sox_reverb_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
 
@@ -150,7 +148,7 @@
 /*
  * Prepare for processing.
  */
-static int sox_reverb_start(eff_t effp)
+static int sox_reverb_start(sox_effect_t effp)
 {
         reverb_t reverb = (reverb_t) effp->priv;
         size_t i;
@@ -203,7 +201,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_reverb_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_reverb_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                    sox_size_t *isamp, sox_size_t *osamp)
 {
         reverb_t reverb = (reverb_t) effp->priv;
@@ -236,7 +234,7 @@
 /*
  * Drain out reverb lines. 
  */
-static int sox_reverb_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_reverb_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         reverb_t reverb = (reverb_t) effp->priv;
         float d_in, d_out;
@@ -273,7 +271,7 @@
 /*
  * Clean up reverb effect.
  */
-static int sox_reverb_stop(eff_t effp)
+static int sox_reverb_stop(sox_effect_t effp)
 {
         reverb_t reverb = (reverb_t) effp->priv;
 
@@ -282,7 +280,7 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_reverb_effect = {
+static sox_effect_handler_t sox_reverb_effect = {
   "reverb",
   "Usage: reverb gain-out reverb-time delay [ delay ... ]",
   SOX_EFF_LENGTH,
@@ -291,10 +289,10 @@
   sox_reverb_flow,
   sox_reverb_drain,
   sox_reverb_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_reverb_effect_fn(void)
+const sox_effect_handler_t *sox_reverb_effect_fn(void)
 {
     return &sox_reverb_effect;
 }
--- a/src/reverse.c
+++ b/src/reverse.c
@@ -20,8 +20,6 @@
 #include <unistd.h>     /* For SEEK_* defines if not found in stdio */
 #endif
 
-static sox_effect_t sox_reverse_effect;
-
 /* Private data */
 typedef struct reversestuff {
         FILE *fp;
@@ -36,7 +34,7 @@
  * Prepare processing: open temporary file.
  */
 
-static int sox_reverse_start(eff_t effp)
+static int sox_reverse_start(sox_effect_t effp)
 {
         reverse_t reverse = (reverse_t) effp->priv;
         reverse->fp = tmpfile();
@@ -53,7 +51,7 @@
  * Effect flow: a degenerate case: write input samples on temporary file,
  * don't generate any output samples.
  */
-static int sox_reverse_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf UNUSED, 
+static int sox_reverse_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf UNUSED, 
                     sox_size_t *isamp, sox_size_t *osamp)
 {
         reverse_t reverse = (reverse_t) effp->priv;
@@ -77,7 +75,7 @@
  * Effect drain: generate the actual samples in reverse order.
  */
 
-static int sox_reverse_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_reverse_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
         reverse_t reverse = (reverse_t) effp->priv;
         sox_size_t len, nbytes;
@@ -123,7 +121,7 @@
 /*
  * Close and unlink the temporary file.
  */
-static int sox_reverse_stop(eff_t effp)
+static int sox_reverse_stop(sox_effect_t effp)
 {
         reverse_t reverse = (reverse_t) effp->priv;
 
@@ -131,19 +129,19 @@
         return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_reverse_effect = {
+static sox_effect_handler_t sox_reverse_effect = {
   "reverse",
   "Usage: Reverse effect takes no options",
   0,
-  sox_effect_nothing_getopts,
+  NULL,
   sox_reverse_start,
   sox_reverse_flow,
   sox_reverse_drain,
   sox_reverse_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_reverse_effect_fn(void)
+const sox_effect_handler_t *sox_reverse_effect_fn(void)
 {
     return &sox_reverse_effect;
 }
--- a/src/silence.c
+++ b/src/silence.c
@@ -18,8 +18,6 @@
 #include <math.h>
 #include "sox_i.h"
 
-static sox_effect_t sox_silence_effect;
-
 /* Private data for silence effect. */
 
 #define SILENCE_TRIM        0
@@ -67,7 +65,7 @@
     char        mode;
 } *silence_t;
 
-static void clear_rms(eff_t effp)
+static void clear_rms(sox_effect_t effp)
 
 {
     silence_t silence = (silence_t) effp->priv;
@@ -80,7 +78,7 @@
     silence->rms_sum = 0;
 }
 
-static int sox_silence_getopts(eff_t effp, int n, char **argv)
+static int sox_silence_getopts(sox_effect_t effp, int n, char **argv)
 {
     silence_t   silence = (silence_t) effp->priv;
     int parse_count;
@@ -97,7 +95,7 @@
 
     if (n < 1)
     {
-        sox_fail(sox_silence_effect.usage);
+        sox_fail(effp->handler.usage);
         return (SOX_EOF);
     }
 
@@ -105,7 +103,7 @@
     silence->start = sox_false;
     if (sscanf(argv[0], "%d", &silence->start_periods) != 1)
     {
-        sox_fail(sox_silence_effect.usage);
+        sox_fail(effp->handler.usage);
         return(SOX_EOF);
     }
     if (silence->start_periods < 0)
@@ -121,7 +119,7 @@
         silence->start = sox_true;
         if (n < 2)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
 
@@ -135,7 +133,7 @@
         if (sox_parsesamples(0,silence->start_duration_str,
                     &silence->start_duration,'s') == NULL)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return(SOX_EOF);
         }
 
@@ -143,7 +141,7 @@
                 &silence->start_unit);
         if (parse_count < 1)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
         else if (parse_count < 2)
@@ -159,12 +157,12 @@
     {
         if (n < 3)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
         if (sscanf(argv[0], "%d", &silence->stop_periods) != 1)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
         if (silence->stop_periods < 0)
@@ -188,7 +186,7 @@
         if (sox_parsesamples(0,silence->stop_duration_str,
                     &silence->stop_duration,'s') == NULL)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return(SOX_EOF);
         }
 
@@ -196,7 +194,7 @@
                              &silence->stop_unit);
         if (parse_count < 1)
         {
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
         }
         else if (parse_count < 2)
@@ -212,7 +210,7 @@
         if ((silence->start_unit != '%') && (silence->start_unit != 'd'))
         {
             sox_fail("Invalid unit specified");
-            sox_fail(sox_silence_effect.usage);
+            sox_fail(effp->handler.usage);
             return(SOX_EOF);
         }
         if ((silence->start_unit == '%') && ((silence->start_threshold < 0.0)
@@ -250,7 +248,7 @@
     return(SOX_SUCCESS);
 }
 
-static int sox_silence_start(eff_t effp)
+static int sox_silence_start(sox_effect_t effp)
 {
         silence_t       silence = (silence_t) effp->priv;
 
@@ -271,7 +269,7 @@
             if (sox_parsesamples(effp->ininfo.rate, silence->start_duration_str,
                                 &silence->start_duration, 's') == NULL)
             {
-                sox_fail(sox_silence_effect.usage);
+                sox_fail(effp->handler.usage);
                 return(SOX_EOF);
             }
         }
@@ -280,7 +278,7 @@
             if (sox_parsesamples(effp->ininfo.rate,silence->stop_duration_str,
                                 &silence->stop_duration,'s') == NULL)
             {
-                sox_fail(sox_silence_effect.usage);
+                sox_fail(effp->handler.usage);
                 return(SOX_EOF);
             }
         }
@@ -303,7 +301,7 @@
         return(SOX_SUCCESS);
 }
 
-static int aboveThreshold(eff_t effp, sox_ssample_t value, double threshold, int unit)
+static int aboveThreshold(sox_effect_t effp, sox_ssample_t value, double threshold, int unit)
 {
     double ratio;
     int rc;
@@ -342,7 +340,7 @@
     return rc;
 }
 
-static sox_ssample_t compute_rms(eff_t effp, sox_ssample_t sample)
+static sox_ssample_t compute_rms(sox_effect_t effp, sox_ssample_t sample)
 {
     silence_t silence = (silence_t) effp->priv;
     double new_sum;
@@ -357,7 +355,7 @@
     return (rms);
 }
 
-static void update_rms(eff_t effp, sox_ssample_t sample)
+static void update_rms(sox_effect_t effp, sox_ssample_t sample)
 {
     silence_t silence = (silence_t) effp->priv;
 
@@ -372,7 +370,7 @@
 
 /* Process signed long samples from ibuf to obuf. */
 /* Return number of samples processed in isamp and osamp. */
-static int sox_silence_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_silence_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                     sox_size_t *isamp, sox_size_t *osamp)
 {
     silence_t silence = (silence_t) effp->priv;
@@ -659,7 +657,7 @@
         return (SOX_SUCCESS);
 }
 
-static int sox_silence_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_silence_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
     silence_t silence = (silence_t) effp->priv;
     sox_size_t i;
@@ -695,7 +693,7 @@
         return SOX_SUCCESS;
 }
 
-static int sox_silence_stop(eff_t effp)
+static int sox_silence_stop(sox_effect_t effp)
 {
     silence_t silence = (silence_t) effp->priv;
 
@@ -705,7 +703,7 @@
     return(SOX_SUCCESS);
 }
 
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
   silence_t silence = (silence_t) effp->priv;
 
@@ -714,7 +712,7 @@
   return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_silence_effect = {
+static sox_effect_handler_t sox_silence_effect = {
   "silence",
   "Usage: silence [ -l ] above_periods [ duration thershold[d|%%] ] [ below_periods duration threshold[d|%%]]",
   SOX_EFF_MCHAN,
@@ -726,7 +724,7 @@
   kill
 };
 
-const sox_effect_t *sox_silence_effect_fn(void)
+const sox_effect_handler_t *sox_silence_effect_fn(void)
 {
     return &sox_silence_effect;
 }
--- a/src/skeleff.c
+++ b/src/skeleff.c
@@ -34,12 +34,12 @@
  * Don't do initialization now.
  * The 'info' fields are not yet filled in.
  */
-static int getopts(eff_t effp, int n, char **argv)
+static int getopts(sox_effect_t effp, int n, char **argv)
 {
   skeleff_t skeleff = (skeleff_t)effp->priv;
 
   if (n && n != 1) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
 
@@ -50,7 +50,7 @@
  * Prepare processing.
  * Do all initializations.
  */
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
   if (effp->outinfo.channels == 1) {
     sox_fail("Can't run skeleff on mono data.");
@@ -64,7 +64,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                            sox_size_t *isamp, sox_size_t *osamp)
 {
   skeleff_t skeleff = (skeleff_t)effp->priv;
@@ -97,7 +97,7 @@
 /*
  * Drain out remaining samples if the effect generates any.
  */
-static int drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   *osamp = 0;
   /* Help out application and return SOX_EOF when drain
@@ -110,7 +110,7 @@
 /*
  * Do anything required when you stop reading samples.  
  */
-static int stop(eff_t effp)
+static int stop(sox_effect_t effp)
 {
   return SOX_SUCCESS;
 }
@@ -119,7 +119,7 @@
  * Do anything required when you kill an effect.  
  *      (free allocated memory, etc.)
  */
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
   return SOX_SUCCESS;
 }
@@ -131,7 +131,7 @@
  * the 6 functions, then the function above can be deleted
  * and 0 used in place of the its name below.
  */
-static sox_effect_t sox_skel_effect = {
+static sox_effect_handler_t sox_skel_effect = {
   "skel",
   "Usage: skel [OPTION]",
   SOX_EFF_MCHAN,
@@ -147,7 +147,7 @@
  * Function returning effect descriptor. This should be the only
  * externally visible object.
  */
-const sox_effect_t *sox_skel_effect_fn(void)
+const sox_effect_handler_t *sox_skel_effect_fn(void)
 {
   return &sox_skel_effect;
 }
--- a/src/skelform.c
+++ b/src/skelform.c
@@ -1,5 +1,5 @@
 /*
- * libSoX skeleton file format driver.
+ * libSoX skeleton file format handler.
  *
  * Copyright 1999 Chris Bagwell And Sundry Contributors
  *
--- a/src/smp.c
+++ b/src/smp.c
@@ -1,5 +1,5 @@
 /*
- * libSoX SampleVision file format driver.
+ * libSoX SampleVision file format handler.
  * Output is always in little-endian (80x86/VAX) order.
  * 
  * Derived from: libSoX skeleton handler file.
--- a/src/sox.c
+++ b/src/sox.c
@@ -79,7 +79,6 @@
 static sox_size_t mixing_clips = 0;
 static sox_bool repeatable_random = sox_false;  /* Whether to invoke srand. */
 static sox_bool interactive = sox_false;
-static sox_effects_global_info_t effects_global_info = {sox_false, 1, &sox_global_info};
 static sox_bool uservolume = sox_false;
 typedef enum {RG_off, RG_track, RG_album} rg_mode;
 static rg_mode replay_gain_mode = RG_off;
@@ -133,7 +132,7 @@
  * effects table.  This is because at most we will need to add
  * a resample effect, a channel mixing effect, the input, and the output.
  */
-#define MAX_USER_EFF (MAX_EFFECTS - 4)
+#define MAX_USER_EFF (SOX_MAX_EFFECTS - 4)
 static struct sox_effect user_efftab[MAX_USER_EFF];
 static unsigned nuser_effects;
 
@@ -364,7 +363,7 @@
   file_t f = NULL;
   struct file_info fi_none;
 
-  while (optind < argc && !is_effect_name(argv[optind])) {
+  while (optind < argc && !sox_find_effect(argv[optind])) {
     f = new_file();
     fi_none = *f;
 
@@ -379,7 +378,7 @@
       f->filetype = "null";
       f->filename = xstrdup("-n");
     } else {
-      if (optind >= argc || is_effect_name(argv[optind]))
+      if (optind >= argc || sox_find_effect(argv[optind]))
         break;
       if (is_playlist(argv[optind])) {
         parse_playlist(f, argv[optind++]);
@@ -429,11 +428,9 @@
 
 static void parse_effects(int argc, char **argv)
 {
-  int argc_effect;
-
   for (nuser_effects = 0; optind < argc; ++nuser_effects) {
     struct sox_effect * e = &user_efftab[nuser_effects];
-    int (*getopts)(eff_t effp, int argc, char *argv[]);
+    int i;
 
     if (nuser_effects >= MAX_USER_EFF) {
       sox_fail("too many effects specified (at most %i allowed)", MAX_USER_EFF);
@@ -440,21 +437,16 @@
       exit(1);
     }
 
-    argc_effect = sox_geteffect_opt(e, argc - optind, &argv[optind]);
-    if (argc_effect == SOX_EOF) {
-      sox_fail("Effect `%s' does not exist!", argv[optind]);
+    sox_get_effect(e, argv[optind++]);  /* Cannot fail */
+
+    for (i = 0; i < argc - optind && !sox_find_effect(argv[optind + i]); ++i);
+    if (e->handler.getopts(e, i, &argv[optind]) == SOX_EOF)
       exit(1);
-    }
-    if (e->h->flags & SOX_EFF_DEPRECATED)
-      sox_warn("Effect `%s' is deprecated and may be removed in a future release; please refer to the manual sox(1) for an alternative effect", e->name);
 
-    optind++; /* Skip past effect name */
-    e->global_info = &effects_global_info;
-    getopts = e->h->getopts?  e->h->getopts : sox_effect_nothing_getopts;
-    if (getopts(e, argc_effect, &argv[optind]) == SOX_EOF)
-      exit(2);
+    optind += i; /* Skip past the effect arguments */
 
-    optind += argc_effect; /* Skip past the effect arguments */
+    if (e->handler.flags & SOX_EFF_DEPRECATED)
+      sox_warn("Effect `%s' is deprecated and may be removed in a future release; please refer to the manual sox(1) for an alternative effect", e->handler.name);
   }
 }
 
@@ -612,7 +604,7 @@
   } while (process() != SOX_EOF && !user_abort && current_input < input_count);
   else process();
 
-  kill_effects();
+  sox_kill_effects();
 
   for (i = 0; i < file_count; ++i)
     if (files[i]->desc->clips != 0)
@@ -762,9 +754,9 @@
    * This hack is a huge time savings when trimming
    * gigs of audio data into managable chunks
    */ 
-  if (input_count == 1 && neffects > 1 && strcmp(effects[1][0].name, "trim") == 0) {
+  if (input_count == 1 && sox_neffects > 1 && strcmp(sox_effects[1][0].handler.name, "trim") == 0) {
     if ((files[0]->desc->h->flags & SOX_FILE_SEEK) && files[0]->desc->seekable){
-      sox_size_t offset = sox_trim_get_start(&effects[1][0]);
+      sox_size_t offset = sox_trim_get_start(&sox_effects[1][0]);
       if (sox_seek(files[0]->desc, offset, SOX_SEEK_SET) != SOX_EOF) { 
         read_wide_samples = offset / files[0]->desc->signal.channels;
         /* Assuming a failed seek stayed where it was.  If the 
@@ -771,7 +763,7 @@
          * seek worked then reset the start location of 
          * trim so that it thinks user didn't request a skip.
          */ 
-        sox_trim_clear_start(&effects[1][0]);
+        sox_trim_clear_start(&sox_effects[1][0]);
       }    
     }        
   }    
@@ -1102,7 +1094,7 @@
 assert_static(sizeof(struct input_combiner) <= SOX_MAX_EFFECT_PRIVSIZE,
               /* else */ input_combiner_PRIVSIZE_too_big);
 
-static int combiner_start(eff_t effp)
+static int combiner_start(sox_effect_t effp)
 {
   input_combiner_t z = (input_combiner_t) effp->priv;
   sox_size_t ws, i;
@@ -1121,7 +1113,7 @@
   return SOX_SUCCESS;
 }
 
-static int combiner_drain(eff_t effp, sox_ssample_t * obuf, sox_size_t * osamp)
+static int combiner_drain(sox_effect_t effp, sox_ssample_t * obuf, sox_size_t * osamp)
 {
   input_combiner_t z = (input_combiner_t) effp->priv;
   sox_size_t ws, s, i;
@@ -1171,7 +1163,7 @@
   return olen? SOX_SUCCESS : SOX_EOF;
 }
 
-static int combiner_stop(eff_t effp)
+static int combiner_stop(sox_effect_t effp)
 {
   input_combiner_t z = (input_combiner_t) effp->priv;
   sox_size_t i;
@@ -1184,16 +1176,16 @@
   return SOX_SUCCESS;
 }
 
-static sox_effect_t const * input_combiner_effect_fn(void)
+static sox_effect_handler_t const * input_combiner_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "input", 0, SOX_EFF_MCHAN,
     0, combiner_start, 0, combiner_drain, combiner_stop, 0
   };
-  return &driver;
+  return &handler;
 }
 
-static int output_flow(eff_t effp UNUSED, sox_ssample_t const * ibuf,
+static int output_flow(sox_effect_t effp UNUSED, sox_ssample_t const * ibuf,
     sox_ssample_t * obuf UNUSED, sox_size_t * isamp, sox_size_t * osamp)
 {
   size_t len;
@@ -1210,34 +1202,25 @@
   return SOX_SUCCESS;
 }
 
-static sox_effect_t const * output_effect_fn(void)
+static sox_effect_handler_t const * output_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "output", 0, SOX_EFF_MCHAN, 0, 0, output_flow, 0, 0, 0
   };
-  return &driver;
+  return &handler;
 }
 
 static void add_default_effect(char const * name, int * effects_mask)
 {
-  struct sox_effect eff;
-  struct sox_effect * e = &eff;
-  int (*getopts)(eff_t effp, int argc, char *argv[]);
+  struct sox_effect e;
 
-  /* Find effect and update initial pointers */
-  sox_geteffect(e, name);
-
-  /* Set up & give default opts for added effects */
-  e->global_info = &effects_global_info;
-  getopts = e->h->getopts?  e->h->getopts : sox_effect_nothing_getopts;
-  if (getopts(e, 0, NULL) == SOX_EOF)
+  sox_get_effect(&e, name);        /* Find effect and update initial pointers */
+  if (e.handler.getopts(&e, 0, NULL) == SOX_EOF)   /* Set up with default opts */
     exit(2);
-
-  add_effect(e, &combiner, &ofile->desc->signal, effects_mask);
+  sox_add_effect(&e, &combiner, &ofile->desc->signal, effects_mask);
 }
 
-/* If needed effects are not given, auto-add at (performance) optimal point.
- */
+/* If needed effects are not given, auto-add at (performance) optimal point. */
 static void add_effects(void)
 {
   unsigned i;
@@ -1254,15 +1237,15 @@
     int user_chan_effects = 0, user_rate_effects = 0;
 
     for (i = 0; i < nuser_effects; i++) {
-      if (user_efftab[i].h->flags & SOX_EFF_CHAN) {
+      if (user_efftab[i].handler.flags & SOX_EFF_CHAN) {
         need_chan = sox_false;
         ++user_chan_effects;
       }
-      if (user_efftab[i].h->flags & SOX_EFF_RATE) {
+      if (user_efftab[i].handler.flags & SOX_EFF_RATE) {
         need_rate = sox_false;
         ++user_rate_effects;
       }
-      if (user_efftab[i].h->flags & SOX_EFF_MCHAN)
+      if (user_efftab[i].handler.flags & SOX_EFF_MCHAN)
         user_mchan = i;
     }
     if (user_chan_effects > 1) {
@@ -1275,9 +1258,8 @@
     }
   }
 
-  eff.h = input_combiner_effect_fn();
-  eff.name = eff.h->name;
-  add_effect(&eff, &combiner, &ofile->desc->signal, &effects_mask);
+  sox_create_effect(&eff, input_combiner_effect_fn());
+  sox_add_effect(&eff, &combiner, &ofile->desc->signal, &effects_mask);
 
   /* Copy user specified effects into the real effects */
   for (i = 0; i <= nuser_effects; i++) {
@@ -1295,16 +1277,65 @@
         need_rate = sox_false;
       }
     if (i < nuser_effects)
-      add_effect(&user_efftab[i], &combiner, &ofile->desc->signal, &effects_mask);
+      sox_add_effect(&user_efftab[i], &combiner, &ofile->desc->signal, &effects_mask);
   }
   if (need_chan)
     add_default_effect("mixer", &effects_mask);
 
-  eff.h = output_effect_fn();
-  eff.name = eff.h->name;
-  add_effect(&eff, &combiner, &ofile->desc->signal, &effects_mask);
+  sox_create_effect(&eff, output_effect_fn());
+  sox_add_effect(&eff, &combiner, &ofile->desc->signal, &effects_mask);
 }
 
+static void open_output_file(sox_size_t olen)
+{
+  sox_loopinfo_t loops[SOX_MAX_NLOOPS];
+  double factor;
+  int i;
+  char const *comment = NULL;
+
+  if (ofile->comment == NULL)
+    comment = files[0]->desc->comment ? files[0]->desc->comment : "Processed by SoX";
+  else if (*ofile->comment != '\0')
+      comment = ofile->comment;
+
+  /*
+   * copy loop info, resizing appropriately
+   * it's in samples, so # channels don't matter
+   * FIXME: This doesn't work for multi-file processing or
+   * effects that change file length.
+   */
+  factor = (double) ofile->signal.rate / combiner.rate;
+  for (i = 0; i < SOX_MAX_NLOOPS; i++) {
+    loops[i].start = files[0]->desc->loops[i].start * factor;
+    loops[i].length = files[0]->desc->loops[i].length * factor;
+    loops[i].count = files[0]->desc->loops[i].count;
+    loops[i].type = files[0]->desc->loops[i].type;
+  }
+
+  ofile->desc = sox_open_write(overwrite_permitted,
+                        ofile->filename,
+                        &ofile->signal,
+                        ofile->filetype,
+                        comment,
+                        olen,
+                        &files[0]->desc->instr,
+                        loops);
+
+  if (!ofile->desc)
+    /* sox_open_write() will call sox_warn for most errors.
+     * Rely on that printing something. */
+    exit(2);
+
+  /* When writing to an audio device, auto turn on the
+   * progress display to match behavior of ogg123,
+   * unless the user requested us not to display anything. */
+  if (show_progress == SOX_OPTION_DEFAULT)
+    show_progress = (ofile->desc->h->flags & SOX_FILE_DEVICE) != 0 &&
+                    (ofile->desc->h->flags & SOX_FILE_PHONY) == 0;
+
+  report_file_info(ofile);
+}
+
 /*
  * Process:   Input(s) -> Balancing -> Combiner -> Effects -> Output
  */
@@ -1368,62 +1399,15 @@
   combiner.rate = combiner.rate * effects_global_info.speed + .5;
 
   for (i = 0; i < nuser_effects; i++)
-    known_length = known_length && !(user_efftab[i].h->flags & SOX_EFF_LENGTH);
+    known_length = known_length && !(user_efftab[i].handler.flags & SOX_EFF_LENGTH);
 
   if (!known_length)
     olen = 0;
 
-  {
-    sox_loopinfo_t loops[SOX_MAX_NLOOPS];
-    double factor;
-    int i;
-    char const *comment = NULL;
+  open_output_file(olen);
 
-    if (ofile->comment == NULL)
-      comment = files[0]->desc->comment ? files[0]->desc->comment : "Processed by SoX";
-    else if (*ofile->comment != '\0')
-        comment = ofile->comment;
-
-    /*
-     * copy loop info, resizing appropriately
-     * it's in samples, so # channels don't matter
-     * FIXME: This doesn't work for multi-file processing or
-     * effects that change file length.
-     */
-    factor = (double) ofile->signal.rate / combiner.rate;
-    for (i = 0; i < SOX_MAX_NLOOPS; i++) {
-      loops[i].start = files[0]->desc->loops[i].start * factor;
-      loops[i].length = files[0]->desc->loops[i].length * factor;
-      loops[i].count = files[0]->desc->loops[i].count;
-      loops[i].type = files[0]->desc->loops[i].type;
-    }
-
-    ofile->desc = sox_open_write(overwrite_permitted,
-                          ofile->filename,
-                          &ofile->signal,
-                          ofile->filetype,
-                          comment,
-                          olen,
-                          &files[0]->desc->instr,
-                          loops);
-
-    if (!ofile->desc)
-      /* sox_open_write() will call sox_warn for most errors.
-       * Rely on that printing something. */
-      exit(2);
-
-    /* When writing to an audio device, auto turn on the
-     * progress display to match behavior of ogg123,
-     * unless the user requested us not to display anything. */
-    if (show_progress == SOX_OPTION_DEFAULT)
-      show_progress = (ofile->desc->h->flags & SOX_FILE_DEVICE) != 0 &&
-                      (ofile->desc->h->flags & SOX_FILE_PHONY) == 0;
-
-    report_file_info(ofile);
-  }
-
   add_effects();
-  if (start_effects() != SOX_SUCCESS)
+  if (sox_start_effects() != SOX_SUCCESS)
     exit(2); /* The failing effect should have displayed an error message */
 
   optimize_trim();
@@ -1431,10 +1415,10 @@
   signal(SIGINT, sigint);
   signal(SIGTERM, sigint);
 
-  flowstatus = flow_effects(update_status, &user_abort);
+  flowstatus = sox_flow_effects(update_status, &user_abort);
 
-  stop_effects();
-  delete_effects();
+  sox_stop_effects();
+  sox_delete_effects();
   return flowstatus;
 }
 
@@ -1445,9 +1429,9 @@
   for (i = 0; i < file_count; ++i)
     clips += files[i]->desc->clips + files[i]->volume_clips;
   clips += mixing_clips;
-  for (i = 1; i < neffects - 1; ++i)
-    for (f = 1; f < effects[i][0].flows; ++f)
-      clips += effects[i][f].clips;
+  for (i = 1; i < sox_neffects - 1; ++i)
+    for (f = 1; f < sox_effects[i][0].flows; ++f)
+      clips += sox_effects[i][f].clips;
   return clips;
 }
 
@@ -1510,7 +1494,7 @@
 {
   size_t i, formats;
   const char **format_list;
-  const sox_effect_t *e;
+  const sox_effect_handler_t *e;
   static char const * lines[] = {
 "SPECIAL FILENAMES:",
 "-               stdin (infile) or stdout (outfile)",
@@ -1607,7 +1591,7 @@
 static void usage_effect(char *effect)
 {
   int i;
-  const sox_effect_t *e;
+  const sox_effect_handler_t *e;
 
   printf("%s: ", myname);
   printf("v%s\n\n", PACKAGE_VERSION);
--- a/src/sox.h
+++ b/src/sox.h
@@ -229,7 +229,7 @@
      * options.)  The physical delineation is in the somewhat
      * snappily-named libSoX function `set_endianness_if_not_already_set'
      * which is called at the right times (as files are openned) by the
-     * libSoX core, not by the file drivers themselves.  The file drivers
+     * libSoX core, not by the file handlers themselves.  The file handlers
      * indicate to the libSoX core if they have a preference using
      * SOX_FILE_xxx flags.
      */
@@ -341,7 +341,7 @@
 /* These two for use by the libSoX core or libSoX clients: */
 #define SOX_FILE_ENDIAN  64 /* is file format endian? */
 #define SOX_FILE_ENDBIG  128/* if so, is it big endian? */
-/* These two for use by libSoX drivers: */
+/* These two for use by libSoX handlers: */
 #define SOX_FILE_LIT_END  (0   + 64)
 #define SOX_FILE_BIG_END  (128 + 64)
 #define SOX_FILE_BIT_REV 256
@@ -372,45 +372,37 @@
  * Handler structure for each effect.
  */
 
-typedef struct sox_effect *eff_t;
+typedef struct sox_effect * sox_effect_t;
 
-typedef struct
-{
-    char const *name;               /* effect name */
-    char const *usage;
-    unsigned int flags;
+typedef struct {
+  char const * name;
+  char const * usage;
+  unsigned int flags;
 
-    int (*getopts)(eff_t effp, int argc, char *argv[]);
-    int (*start)(eff_t effp);
-    int (*flow)(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
-                sox_size_t *isamp, sox_size_t *osamp);
-    int (*drain)(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
-    int (*stop)(eff_t effp);
-    int (*kill)(eff_t effp);
-} sox_effect_t;
+  int (*getopts)(sox_effect_t effp, int argc, char *argv[]);
+  int (*start)(sox_effect_t effp);
+  int (*flow)(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
+              sox_size_t *isamp, sox_size_t *osamp);
+  int (*drain)(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
+  int (*stop)(sox_effect_t effp);
+  int (*kill)(sox_effect_t effp);
+} sox_effect_handler_t;
 
-struct sox_effect
-{
-    char const *name;               /* effect name */
-    sox_size_t       flows;
-    struct sox_effects_global_info * global_info;/* global parameters */
-    struct sox_signalinfo ininfo;    /* input signal specifications */
-    struct sox_signalinfo outinfo;   /* output signal specifications */
-    const sox_effect_t *h;           /* effects driver */
-    sox_ssample_t     *obuf;          /* output buffer */
-    sox_size_t       odone, olen;    /* consumed, total length */
-    sox_size_t       clips;   /* increment if clipping occurs */
-    /* The following is a portable trick to align this variable on
-     * an 8-byte boundary.  Once this is done, the buffer alloced
-     * after it should be align on an 8-byte boundery as well.
-     * This lets you cast any structure over the private area
-     * without concerns of alignment.
-     */
-    double priv1;
-    char priv[SOX_MAX_EFFECT_PRIVSIZE]; /* private area for effect */
+struct sox_effect {
+  /* Placing priv at the start of this structure ensures that it gets aligned
+   * in memory in the optimal way for any structure to be cast over it. */
+  char priv[SOX_MAX_EFFECT_PRIVSIZE];    /* private area for effect */
+
+  struct sox_effects_global_info * global_info; /* global parameters */
+  struct sox_signalinfo    ininfo;       /* input signal specifications */
+  struct sox_signalinfo    outinfo;      /* output signal specifications */
+  sox_effect_handler_t     handler;
+  sox_ssample_t            * obuf;       /* output buffer */
+  sox_size_t               odone, olen;  /* consumed, total length */
+  sox_size_t               clips;        /* increment if clipping occurs */
+  sox_size_t               flows;
 };
 
-void set_endianness_if_not_already_set(ft_t ft);
 extern ft_t sox_open_read(const char *path, const sox_signalinfo_t *info, 
                          const char *filetype);
 ft_t sox_open_write(
@@ -429,20 +421,21 @@
 #define SOX_SEEK_SET 0
 extern int sox_seek(ft_t ft, sox_size_t offset, int whence);
 
-int sox_geteffect_opt(eff_t effp, int argc, char **argv);
-int sox_geteffect(eff_t effp, const char *effect_name);
-sox_bool is_effect_name(char const *text);
-int sox_updateeffect(eff_t effp, const sox_signalinfo_t *in, const sox_signalinfo_t *out, int effect_mask);
+sox_effect_handler_t const * sox_find_effect(char const * name);
+int sox_create_effect(sox_effect_t effp, sox_effect_handler_t const * e);
+int sox_get_effect(sox_effect_t effp, const char * name);
+int sox_update_effect(sox_effect_t effp, const sox_signalinfo_t *in, const sox_signalinfo_t *out, int effect_mask);
 
-#define MAX_EFFECTS 20
-extern struct sox_effect * effects[MAX_EFFECTS];
-extern unsigned neffects;                     /* # of effects to run on data */
-void add_effect(struct sox_effect * e, sox_signalinfo_t * in, sox_signalinfo_t * out, int * effects_mask);
-int start_effects(void);
-int flow_effects(void (* update_status)(sox_bool), sox_bool * user_abort);
-void stop_effects(void);
-void kill_effects(void);
-void delete_effects(void);
+/* Effects chain */
+#define SOX_MAX_EFFECTS 20
+extern sox_effect_t sox_effects[SOX_MAX_EFFECTS];
+extern unsigned sox_neffects;
+int sox_add_effect(sox_effect_t e, sox_signalinfo_t * in, sox_signalinfo_t * out, int * effects_mask);
+int sox_start_effects(void);
+int sox_flow_effects(void (* update_status)(sox_bool), sox_bool * user_abort);
+void sox_stop_effects(void);
+void sox_kill_effects(void);
+void sox_delete_effects(void);
 
 int sox_gettype(ft_t, sox_bool);
 ft_t sox_initformat(void);
@@ -457,15 +450,15 @@
  * wants to trim and use a sox_seek() operation instead.  After
  * sox_seek()'ing, you should set the trim option to 0.
  */
-sox_size_t sox_trim_get_start(eff_t effp);
-void sox_trim_clear_start(eff_t effp);
+sox_size_t sox_trim_get_start(sox_effect_t effp);
+void sox_trim_clear_start(sox_effect_t effp);
 
 extern char const * sox_message_filename;
 
-#define SOX_EOF (-1)
-#define SOX_SUCCESS (0)
+#define SOX_SUCCESS 0
+#define SOX_EOF (-1)           /* End Of File or other error */
 
-const char *sox_version(void);                   /* return version number */
+const char *sox_version(void);   /* Returns version number */
 
 /* libSoX specific error codes.  The rest directly map from errno. */
 #define SOX_EHDR 2000            /* Invalid Audio Header */
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -139,6 +139,7 @@
 size_t sox_writebuf(ft_t ft, void const *buf, sox_size_t len);
 int sox_reads(ft_t ft, char *c, sox_size_t len);
 int sox_writes(ft_t ft, char const * c);
+void set_endianness_if_not_already_set(ft_t ft);
 
 sox_size_t sox_read_b_buf(ft_t ft, uint8_t *buf, sox_size_t len);
 sox_size_t sox_read_w_buf(ft_t ft, uint16_t *buf, sox_size_t len);
@@ -238,6 +239,7 @@
  */
 extern sox_size_t sox_bufsiz;
 extern sox_global_info_t sox_global_info;
+extern sox_effects_global_info_t effects_global_info;
 
 extern const char sox_readerr[];
 extern const char sox_writerr[];
@@ -277,10 +279,6 @@
 sox_size_t sox_format_nothing_read(ft_t ft, sox_ssample_t *buf, sox_size_t len);
 sox_size_t sox_format_nothing_write(ft_t ft, const sox_ssample_t *buf, sox_size_t len);
 int sox_format_nothing_seek(ft_t ft, sox_size_t offset);
-int sox_effect_nothing(eff_t effp);
-int sox_effect_nothing_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, sox_size_t *isamp, sox_size_t *osamp);
-int sox_effect_nothing_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
-int sox_effect_nothing_getopts(eff_t effp, int n, char **argv UNUSED);
 
 int sox_rawstart(ft_t ft, sox_bool default_rate, sox_bool default_channels, sox_encoding_t encoding, int size);
 #define sox_rawstartread(ft) sox_rawstart(ft, sox_false, sox_false, SOX_ENCODING_UNKNOWN, -1)
@@ -293,68 +291,68 @@
  *=============================================================================
  */
 
-typedef const sox_effect_t *(*sox_effect_fn_t)(void);
+typedef const sox_effect_handler_t *(*sox_effect_fn_t)(void);
 
 extern sox_effect_fn_t sox_effect_fns[];
 
-extern const sox_effect_t *sox_allpass_effect_fn(void);
-extern const sox_effect_t *sox_avg_effect_fn(void);
-extern const sox_effect_t *sox_band_effect_fn(void);
-extern const sox_effect_t *sox_bandpass_effect_fn(void);
-extern const sox_effect_t *sox_bandreject_effect_fn(void);
-extern const sox_effect_t *sox_bass_effect_fn(void);
-extern const sox_effect_t *sox_chorus_effect_fn(void);
-extern const sox_effect_t *sox_compand_effect_fn(void);
-extern const sox_effect_t *sox_dcshift_effect_fn(void);
-extern const sox_effect_t *sox_deemph_effect_fn(void);
-extern const sox_effect_t *sox_dither_effect_fn(void);
-extern const sox_effect_t *sox_earwax_effect_fn(void);
-extern const sox_effect_t *sox_echo_effect_fn(void);
-extern const sox_effect_t *sox_echos_effect_fn(void);
-extern const sox_effect_t *sox_equalizer_effect_fn(void);
-extern const sox_effect_t *sox_fade_effect_fn(void);
-extern const sox_effect_t *sox_filter_effect_fn(void);
-extern const sox_effect_t *sox_flanger_effect_fn(void);
-extern const sox_effect_t *sox_highpass_effect_fn(void);
-extern const sox_effect_t *sox_highp_effect_fn(void);
-extern const sox_effect_t *sox_lowpass_effect_fn(void);
-extern const sox_effect_t *sox_lowp_effect_fn(void);
-extern const sox_effect_t *sox_mask_effect_fn(void);
-extern const sox_effect_t *sox_mcompand_effect_fn(void);
-extern const sox_effect_t *sox_mixer_effect_fn(void);
-extern const sox_effect_t *sox_noiseprof_effect_fn(void);
-extern const sox_effect_t *sox_noisered_effect_fn(void);
-extern const sox_effect_t *sox_pad_effect_fn(void);
-extern const sox_effect_t *sox_pan_effect_fn(void);
-extern const sox_effect_t *sox_phaser_effect_fn(void);
-extern const sox_effect_t *sox_pick_effect_fn(void);
-extern const sox_effect_t *sox_pitch_effect_fn(void);
-extern const sox_effect_t *sox_polyphase_effect_fn(void);
+extern const sox_effect_handler_t *sox_allpass_effect_fn(void);
+extern const sox_effect_handler_t *sox_avg_effect_fn(void);
+extern const sox_effect_handler_t *sox_band_effect_fn(void);
+extern const sox_effect_handler_t *sox_bandpass_effect_fn(void);
+extern const sox_effect_handler_t *sox_bandreject_effect_fn(void);
+extern const sox_effect_handler_t *sox_bass_effect_fn(void);
+extern const sox_effect_handler_t *sox_chorus_effect_fn(void);
+extern const sox_effect_handler_t *sox_compand_effect_fn(void);
+extern const sox_effect_handler_t *sox_dcshift_effect_fn(void);
+extern const sox_effect_handler_t *sox_deemph_effect_fn(void);
+extern const sox_effect_handler_t *sox_dither_effect_fn(void);
+extern const sox_effect_handler_t *sox_earwax_effect_fn(void);
+extern const sox_effect_handler_t *sox_echo_effect_fn(void);
+extern const sox_effect_handler_t *sox_echos_effect_fn(void);
+extern const sox_effect_handler_t *sox_equalizer_effect_fn(void);
+extern const sox_effect_handler_t *sox_fade_effect_fn(void);
+extern const sox_effect_handler_t *sox_filter_effect_fn(void);
+extern const sox_effect_handler_t *sox_flanger_effect_fn(void);
+extern const sox_effect_handler_t *sox_highpass_effect_fn(void);
+extern const sox_effect_handler_t *sox_highp_effect_fn(void);
+extern const sox_effect_handler_t *sox_lowpass_effect_fn(void);
+extern const sox_effect_handler_t *sox_lowp_effect_fn(void);
+extern const sox_effect_handler_t *sox_mask_effect_fn(void);
+extern const sox_effect_handler_t *sox_mcompand_effect_fn(void);
+extern const sox_effect_handler_t *sox_mixer_effect_fn(void);
+extern const sox_effect_handler_t *sox_noiseprof_effect_fn(void);
+extern const sox_effect_handler_t *sox_noisered_effect_fn(void);
+extern const sox_effect_handler_t *sox_pad_effect_fn(void);
+extern const sox_effect_handler_t *sox_pan_effect_fn(void);
+extern const sox_effect_handler_t *sox_phaser_effect_fn(void);
+extern const sox_effect_handler_t *sox_pick_effect_fn(void);
+extern const sox_effect_handler_t *sox_pitch_effect_fn(void);
+extern const sox_effect_handler_t *sox_polyphase_effect_fn(void);
 #ifdef HAVE_SAMPLERATE_H
-extern const sox_effect_t *sox_rabbit_effect_fn(void);
+extern const sox_effect_handler_t *sox_rabbit_effect_fn(void);
 #endif
-extern const sox_effect_t *sox_rate_effect_fn(void);
-extern const sox_effect_t *sox_repeat_effect_fn(void);
-extern const sox_effect_t *sox_resample_effect_fn(void);
-extern const sox_effect_t *sox_reverb_effect_fn(void);
-extern const sox_effect_t *sox_reverse_effect_fn(void);
-extern const sox_effect_t *sox_silence_effect_fn(void);
-extern const sox_effect_t *sox_speed_effect_fn(void);
-extern const sox_effect_t *sox_stat_effect_fn(void);
-extern const sox_effect_t *sox_stretch_effect_fn(void);
-extern const sox_effect_t *sox_swap_effect_fn(void);
-extern const sox_effect_t *sox_synth_effect_fn(void);
-extern const sox_effect_t *sox_treble_effect_fn(void);
-extern const sox_effect_t *sox_tremolo_effect_fn(void);
-extern const sox_effect_t *sox_trim_effect_fn(void);
-extern const sox_effect_t *sox_vibro_effect_fn(void);
-extern const sox_effect_t *sox_vol_effect_fn(void);
+extern const sox_effect_handler_t *sox_rate_effect_fn(void);
+extern const sox_effect_handler_t *sox_repeat_effect_fn(void);
+extern const sox_effect_handler_t *sox_resample_effect_fn(void);
+extern const sox_effect_handler_t *sox_reverb_effect_fn(void);
+extern const sox_effect_handler_t *sox_reverse_effect_fn(void);
+extern const sox_effect_handler_t *sox_silence_effect_fn(void);
+extern const sox_effect_handler_t *sox_speed_effect_fn(void);
+extern const sox_effect_handler_t *sox_stat_effect_fn(void);
+extern const sox_effect_handler_t *sox_stretch_effect_fn(void);
+extern const sox_effect_handler_t *sox_swap_effect_fn(void);
+extern const sox_effect_handler_t *sox_synth_effect_fn(void);
+extern const sox_effect_handler_t *sox_treble_effect_fn(void);
+extern const sox_effect_handler_t *sox_tremolo_effect_fn(void);
+extern const sox_effect_handler_t *sox_trim_effect_fn(void);
+extern const sox_effect_handler_t *sox_vibro_effect_fn(void);
+extern const sox_effect_handler_t *sox_vol_effect_fn(void);
 
 /* Needed in rate.c */
-int sox_resample_start(eff_t effp);
-int sox_resample_getopts(eff_t effp, int n, char **argv);
-int sox_resample_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, sox_size_t *isamp, sox_size_t *osamp);
-int sox_resample_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
-int sox_resample_stop(eff_t effp);
+int sox_resample_start(sox_effect_t effp);
+int sox_resample_getopts(sox_effect_t effp, int n, char **argv);
+int sox_resample_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, sox_size_t *isamp, sox_size_t *osamp);
+int sox_resample_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp);
+int sox_resample_stop(sox_effect_t effp);
 
 #endif
--- a/src/soxconfig.h.cmake
+++ b/src/soxconfig.h.cmake
@@ -18,7 +18,6 @@
 #cmakedefine HAVE_LIBVORBIS           1
 #cmakedefine HAVE_LTDL_H              1
 #cmakedefine HAVE_MACHINE_SOUNDCARD_H 1
-#cmakedefine HAVE_MSVC                1
 #cmakedefine HAVE_POPEN               1
 #cmakedefine HAVE_SAMPLERATE_H        1
 #cmakedefine HAVE_SNDFILE_1_0_12      1
--- a/src/soxio.c
+++ b/src/soxio.c
@@ -12,9 +12,6 @@
 #endif
 
 
-sox_size_t sox_bufsiz = 8192;
-sox_global_info_t sox_global_info;
-
 void set_endianness_if_not_already_set(ft_t ft)
 {
   if (ft->signal.reverse_bytes == SOX_OPTION_DEFAULT) {
--- a/src/speed.c
+++ b/src/speed.c
@@ -27,7 +27,7 @@
 #include <math.h>
 #include <string.h>
 
-static int getopts(eff_t effp, int n, char * * argv)
+static int getopts(sox_effect_t effp, int n, char * * argv)
 {
   sox_bool is_cents = sox_false;
   double speed;
@@ -47,14 +47,14 @@
       }
     }
   }
-  sox_fail(effp->h->usage);
+  sox_fail(effp->handler.usage);
   return SOX_EOF;
 }
 
-sox_effect_t const *sox_speed_effect_fn(void)
+sox_effect_handler_t const *sox_speed_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "speed", "Usage: speed factor[c]", SOX_EFF_NULL|SOX_EFF_LENGTH,
     getopts, 0, 0, 0, 0, 0};
-  return &driver;
+  return &handler;
 }
--- a/src/stat.c
+++ b/src/stat.c
@@ -42,7 +42,7 @@
 /*
  * Process options
  */
-static int sox_stat_getopts(eff_t effp, int n, char **argv)
+static int sox_stat_getopts(sox_effect_t effp, int n, char **argv)
 {
   stat_t stat = (stat_t) effp->priv;
 
@@ -82,7 +82,7 @@
 /*
  * Prepare processing.
  */
-static int sox_stat_start(eff_t effp)
+static int sox_stat_start(sox_effect_t effp)
 {
   stat_t stat = (stat_t) effp->priv;
   int i;
@@ -129,7 +129,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_stat_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
+static int sox_stat_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf,
                         sox_size_t *isamp, sox_size_t *osamp)
 {
   stat_t stat = (stat_t) effp->priv;
@@ -201,7 +201,7 @@
 /*
  * Process tail of input samples.
  */
-static int sox_stat_drain(eff_t effp, sox_ssample_t *obuf UNUSED, sox_size_t *osamp)
+static int sox_stat_drain(sox_effect_t effp, sox_ssample_t *obuf UNUSED, sox_size_t *osamp)
 {
   stat_t stat = (stat_t) effp->priv;
 
@@ -226,7 +226,7 @@
  * Do anything required when you stop reading samples.
  * Don't close input file!
  */
-static int sox_stat_stop(eff_t effp)
+static int sox_stat_stop(sox_effect_t effp)
 {
   stat_t stat = (stat_t) effp->priv;
   double amp, scale, rms = 0, freq;
@@ -318,7 +318,7 @@
 
 }
 
-static sox_effect_t sox_stat_effect = {
+static sox_effect_handler_t sox_stat_effect = {
   "stat",
   "Usage: [ -s N ] [ -rms ] [-freq] [ -v ] [ -d ]",
   SOX_EFF_MCHAN,
@@ -327,10 +327,10 @@
   sox_stat_flow,
   sox_stat_drain,
   sox_stat_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_stat_effect_fn(void)
+const sox_effect_handler_t *sox_stat_effect_fn(void)
 {
   return &sox_stat_effect;
 }
--- a/src/stretch.c
+++ b/src/stretch.c
@@ -25,8 +25,6 @@
 #include <string.h>
 #include <assert.h>
 
-static sox_effect_t sox_stretch_effect;
-
 #define DEFAULT_SLOW_SHIFT_RATIO        0.8
 #define DEFAULT_FAST_SHIFT_RATIO        1.0
 
@@ -72,7 +70,7 @@
 /*
  * Process options
  */
-static int sox_stretch_getopts(eff_t effp, int n, char **argv) 
+static int sox_stretch_getopts(sox_effect_t effp, int n, char **argv) 
 {
   char usage[1024];
   stretch_t stretch = (stretch_t) effp->priv; 
@@ -83,13 +81,13 @@
   stretch->fade = sox_linear_fading;
 
   if (n > 0 && !sscanf(argv[0], "%lf", &stretch->factor)) {
-    sprintf(usage, "%s\n\terror while parsing factor", sox_stretch_effect.usage);
+    sprintf(usage, "%s\n\terror while parsing factor", effp->handler.usage);
     sox_fail(usage);
     return SOX_EOF;
   }
 
   if (n > 1 && !sscanf(argv[1], "%lf", &stretch->window)) {
-    sprintf(usage, "%s\n\terror while parsing window size", sox_stretch_effect.usage);
+    sprintf(usage, "%s\n\terror while parsing window size", effp->handler.usage);
     sox_fail(usage);
     return SOX_EOF;
   }
@@ -101,7 +99,7 @@
       stretch->fade = sox_linear_fading;
       break;
     default:
-      sprintf (usage, "%s\n\terror while parsing fade type", sox_stretch_effect.usage);
+      sprintf (usage, "%s\n\terror while parsing fade type", effp->handler.usage);
       sox_fail(usage);
       return SOX_EOF;
     }
@@ -112,13 +110,13 @@
     DEFAULT_FAST_SHIFT_RATIO: DEFAULT_SLOW_SHIFT_RATIO;
  
   if (n > 3 && !sscanf(argv[3], "%lf", &stretch->shift)) {
-    sprintf (usage, "%s\n\terror while parsing shift ratio", sox_stretch_effect.usage);
+    sprintf (usage, "%s\n\terror while parsing shift ratio", effp->handler.usage);
     sox_fail(usage);
     return SOX_EOF;
   }
 
   if (stretch->shift > 1.0 || stretch->shift <= 0.0) {
-    sprintf(usage, "%s\n\terror with shift ratio value", sox_stretch_effect.usage);
+    sprintf(usage, "%s\n\terror with shift ratio value", effp->handler.usage);
     sox_fail(usage);
     return SOX_EOF;
   }
@@ -133,13 +131,13 @@
     stretch->fading = 0.5;
   
   if (n > 4 && !sscanf(argv[4], "%lf", &stretch->fading)) {
-    sprintf(usage, "%s\n\terror while parsing fading ratio", sox_stretch_effect.usage);
+    sprintf(usage, "%s\n\terror while parsing fading ratio", effp->handler.usage);
     sox_fail(usage);
     return SOX_EOF;
   }
 
   if (stretch->fading > 0.5 || stretch->fading < 0.0) {
-    sprintf(usage, "%s\n\terror with fading ratio value", sox_stretch_effect.usage);
+    sprintf(usage, "%s\n\terror with fading ratio value", effp->handler.usage);
     sox_fail(usage);
     return SOX_EOF;
   }
@@ -150,7 +148,7 @@
 /*
  * Start processing
  */
-static int sox_stretch_start(eff_t effp)
+static int sox_stretch_start(sox_effect_t effp)
 {
   stretch_t stretch = (stretch_t)effp->priv;
   sox_size_t i;
@@ -244,7 +242,7 @@
 /*
  * Processes flow.
  */
-static int sox_stretch_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_stretch_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                     sox_size_t *isamp, sox_size_t *osamp)
 {
   stretch_t stretch = (stretch_t) effp->priv;
@@ -311,7 +309,7 @@
  * Drain buffer at the end
  * maybe not correct ? end might be artificially faded?
  */
-static int sox_stretch_drain(eff_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
+static int sox_stretch_drain(sox_effect_t effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   stretch_t stretch = (stretch_t) effp->priv;
   sox_size_t i;
@@ -345,7 +343,7 @@
  * Do anything required when you stop reading samples.  
  * Don't close input file! 
  */
-static int sox_stretch_stop(eff_t effp)
+static int sox_stretch_stop(sox_effect_t effp)
 {
   stretch_t stretch = (stretch_t) effp->priv;
 
@@ -356,7 +354,7 @@
   return SOX_SUCCESS;
 }
 
-static sox_effect_t sox_stretch_effect = {
+static sox_effect_handler_t sox_stretch_effect = {
   "stretch",
   "Usage: stretch factor [window fade shift fading]\n"
   "       (expansion, frame in ms, lin/..., unit<1.0, unit<0.5)\n"
@@ -367,10 +365,10 @@
   sox_stretch_flow,
   sox_stretch_drain,
   sox_stretch_stop,
-  sox_effect_nothing
+  NULL
 };
 
-const sox_effect_t *sox_stretch_effect_fn(void)
+const sox_effect_handler_t *sox_stretch_effect_fn(void)
 {
   return &sox_stretch_effect;
 }
--- a/src/sunaudio.c
+++ b/src/sunaudio.c
@@ -1,7 +1,7 @@
 /* Direct to Sun Audio Driver
  *
  * Added by Chris Bagwell (cbagwell@sprynet.com) on 2/26/96
- * Based on oss driver.
+ * Based on oss handler.
  *
  * Cleaned up changes of format somewhat in sunstartwrite on 03/31/98
  *
--- a/src/swap.c
+++ b/src/swap.c
@@ -13,8 +13,6 @@
 
 #include "sox_i.h"
 
-static sox_effect_t sox_swap_effect;
-
 typedef struct swapstuff {
     int         order[4];
     int         def_opts;
@@ -26,7 +24,7 @@
  * Don't do initialization now.
  * The 'info' fields are not yet filled in.
  */
-static int sox_swap_getopts(eff_t effp, int n, char **argv) 
+static int sox_swap_getopts(sox_effect_t effp, int n, char **argv) 
 {
     swap_t swap = (swap_t) effp->priv;
 
@@ -36,7 +34,7 @@
         swap->def_opts = 0;
         if (n != 2 && n != 4)
         {
-            sox_fail(sox_swap_effect.usage);
+            sox_fail(effp->handler.usage);
             return (SOX_EOF);
         }
         else if (n == 2)
@@ -62,7 +60,7 @@
  * Prepare processing.
  * Do all initializations.
  */
-static int sox_swap_start(eff_t effp)
+static int sox_swap_start(sox_effect_t effp)
 {
     swap_t swap = (swap_t) effp->priv;
     int i;
@@ -133,7 +131,7 @@
  * Processed signed long samples from ibuf to obuf.
  * Return number of samples processed.
  */
-static int sox_swap_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_swap_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                  sox_size_t *isamp, sox_size_t *osamp)
 {
     swap_t swap = (swap_t) effp->priv;
@@ -183,7 +181,7 @@
     return (SOX_SUCCESS);
 }
 
-static sox_effect_t sox_swap_effect = {
+static sox_effect_handler_t sox_swap_effect = {
   "swap",
   "Usage: swap [1 2 | 1 2 3 4]",
   SOX_EFF_MCHAN,
@@ -190,12 +188,12 @@
   sox_swap_getopts,
   sox_swap_start,
   sox_swap_flow,
-  sox_effect_nothing_drain,
-  sox_effect_nothing,
-  sox_effect_nothing  
+  NULL,
+  NULL,
+  NULL  
 };
 
-const sox_effect_t *sox_swap_effect_fn(void)
+const sox_effect_handler_t *sox_swap_effect_fn(void)
 {
     return &sox_swap_effect;
 }
--- a/src/synth.c
+++ b/src/synth.c
@@ -278,7 +278,7 @@
 
 
 
-static int getopts(eff_t effp, int argc, char **argv)
+static int getopts(sox_effect_t effp, int argc, char **argv)
 {
   synth_t synth = (synth_t) effp->priv;
   int argn = 0;
@@ -289,7 +289,7 @@
     strcpy(synth->length_str, argv[argn]);
     /* Do a dummy parse of to see if it will fail */
     if (sox_parsesamples(0, synth->length_str, &synth->samples_to_do, 't') == NULL) {
-      sox_fail(effp->h->usage);
+      sox_fail(effp->handler.usage);
       return SOX_EOF;
     }
     argn++;
@@ -380,7 +380,7 @@
 
 
 
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
   synth_t synth = (synth_t) effp->priv;
   unsigned i;
@@ -391,7 +391,7 @@
 
   if (synth->length_str)
     if (sox_parsesamples(effp->ininfo.rate, synth->length_str, &synth->samples_to_do, 't') == NULL) {
-      sox_fail(effp->h->usage);
+      sox_fail(effp->handler.usage);
       return SOX_EOF;
     }
 
@@ -564,7 +564,7 @@
 
 
 
-static int flow(eff_t effp, const sox_ssample_t * ibuf, sox_ssample_t * obuf,
+static int flow(sox_effect_t effp, const sox_ssample_t * ibuf, sox_ssample_t * obuf,
     sox_size_t * isamp, sox_size_t * osamp)
 {
   synth_t synth = (synth_t) effp->priv;
@@ -583,7 +583,7 @@
 
 
 
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
   synth_t synth = (synth_t) effp->priv;
   free(synth->channels);
@@ -593,12 +593,12 @@
 
 
 
-const sox_effect_t *sox_synth_effect_fn(void)
+const sox_effect_handler_t *sox_synth_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "synth",
     "Usage: synth [len] {type [combine] [freq[-freq2] [off [ph [p1 [p2 [p3]]]]]]}",
     SOX_EFF_MCHAN, getopts, start, flow, 0, 0, kill
   };
-  return &driver;
+  return &handler;
 }
--- a/src/tremolo.c
+++ b/src/tremolo.c
@@ -18,7 +18,7 @@
 
 #include "sox_i.h"
 
-static int getopts(eff_t effp, int n, char * * argv) 
+static int getopts(sox_effect_t effp, int n, char * * argv) 
 {
   double speed, depth = 40;
   char dummy;     /* To check for extraneous chars. */
@@ -29,7 +29,7 @@
       sscanf(argv[0], "%lf %c", &speed, &dummy) != 1 || speed < 0 ||
       (n > 1 && sscanf(argv[1], "%lf %c", &depth, &dummy) != 1) ||
       depth <= 0 || depth > 100) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   args[2] = argv[0];
@@ -38,12 +38,12 @@
   return sox_synth_effect_fn()->getopts(effp, array_length(args), args);
 }
 
-sox_effect_t const * sox_tremolo_effect_fn(void)
+sox_effect_handler_t const * sox_tremolo_effect_fn(void)
 {
-  static sox_effect_t driver;
-  driver = *sox_synth_effect_fn();
-  driver.name = "tremolo";
-  driver.usage = "Usage: tremolo speed_Hz [depth_percent]";
-  driver.getopts = getopts;
-  return &driver;
+  static sox_effect_handler_t handler;
+  handler = *sox_synth_effect_fn();
+  handler.name = "tremolo";
+  handler.usage = "Usage: tremolo speed_Hz [depth_percent]";
+  handler.getopts = getopts;
+  return &handler;
 }
--- a/src/trim.c
+++ b/src/trim.c
@@ -14,8 +14,6 @@
 #include "sox_i.h"
 #include <string.h>
 
-static sox_effect_t sox_trim_effect;
-
 /* Time resolutin one millisecond */
 #define TIMERES 1000
 
@@ -37,7 +35,7 @@
 /*
  * Process options
  */
-static int sox_trim_getopts(eff_t effp, int n, char **argv) 
+static int sox_trim_getopts(sox_effect_t effp, int n, char **argv) 
 {
     trim_t trim = (trim_t) effp->priv;
 
@@ -51,7 +49,7 @@
             /* Do a dummy parse to see if it will fail */
             if (sox_parsesamples(0, trim->length_str, &trim->length, 't') == NULL)
             {
-                sox_fail(sox_trim_effect.usage);
+                sox_fail(effp->handler.usage);
                 return(SOX_EOF);
             }
         case 1:
@@ -60,12 +58,12 @@
             /* Do a dummy parse to see if it will fail */
             if (sox_parsesamples(0, trim->start_str, &trim->start, 't') == NULL)
             {
-                sox_fail(sox_trim_effect.usage);
+                sox_fail(effp->handler.usage);
                 return(SOX_EOF);
             }
             break;
         default:
-            sox_fail(sox_trim_effect.usage);
+            sox_fail(effp->handler.usage);
             return SOX_EOF;
             break;
 
@@ -76,7 +74,7 @@
 /*
  * Start processing
  */
-static int sox_trim_start(eff_t effp)
+static int sox_trim_start(sox_effect_t effp)
 {
     trim_t trim = (trim_t) effp->priv;
 
@@ -83,7 +81,7 @@
     if (sox_parsesamples(effp->ininfo.rate, trim->start_str,
                         &trim->start, 't') == NULL)
     {
-        sox_fail(sox_trim_effect.usage);
+        sox_fail(effp->handler.usage);
         return(SOX_EOF);
     }
     /* Account for # of channels */
@@ -94,7 +92,7 @@
         if (sox_parsesamples(effp->ininfo.rate, trim->length_str,
                     &trim->length, 't') == NULL)
         {
-            sox_fail(sox_trim_effect.usage);
+            sox_fail(effp->handler.usage);
             return(SOX_EOF);
         }
     }
@@ -116,7 +114,7 @@
  * Place in buf[].
  * Return number of samples read.
  */
-static int sox_trim_flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int sox_trim_flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                  sox_size_t *isamp, sox_size_t *osamp)
 {
     int result = SOX_SUCCESS;
@@ -171,7 +169,7 @@
     return result;
 }
 
-static int kill(eff_t effp)
+static int kill(sox_effect_t effp)
 {
     trim_t trim = (trim_t) effp->priv;
 
@@ -181,19 +179,19 @@
     return (SOX_SUCCESS);
 }
 
-sox_size_t sox_trim_get_start(eff_t effp)          
+sox_size_t sox_trim_get_start(sox_effect_t effp)          
 {        
     trim_t trim = (trim_t)effp->priv;    
     return trim->start;          
 }        
 
-void sox_trim_clear_start(eff_t effp)     
+void sox_trim_clear_start(sox_effect_t effp)     
 {        
     trim_t trim = (trim_t)effp->priv;    
     trim->start = 0;     
 }
 
-static sox_effect_t sox_trim_effect = {
+static sox_effect_handler_t sox_trim_effect = {
   "trim",
   "Usage: trim start [length]",
   SOX_EFF_MCHAN|SOX_EFF_LENGTH,
@@ -200,12 +198,12 @@
   sox_trim_getopts,
   sox_trim_start,
   sox_trim_flow,
-  sox_effect_nothing_drain,
-  sox_effect_nothing,
+  NULL,
+  NULL,
   kill
 };
 
-const sox_effect_t *sox_trim_effect_fn(void)
+const sox_effect_handler_t *sox_trim_effect_fn(void)
 {
     return &sox_trim_effect;
 }
--- a/src/tx16w.c
+++ b/src/tx16w.c
@@ -19,7 +19,7 @@
  *
  * January 12, 1995
  * Copyright 1995 Mark Lakata (lakata@physics.berkeley.edu)
- * Additions to tx16w.c SOX driver.  This version writes as well as
+ * Additions to tx16w.c SOX handler.  This version writes as well as
  * reads TX16W format.
  *
  * July 31, 1998
@@ -34,10 +34,6 @@
  */
 
 #define TXMAXLEN 0x3FF80
-
-/*
- * libSoX skeleton file format driver.
- */
 
 #include <stdio.h>
 #include <string.h>
--- a/src/util.c
+++ b/src/util.c
@@ -16,34 +16,40 @@
 #include <ctype.h>
 #include <stdarg.h>
 
+sox_size_t sox_bufsiz = 8192;
 sox_output_message_handler_t sox_output_message_handler = NULL;
 unsigned sox_output_verbosity_level = 2;
 
+sox_global_info_t sox_global_info;
+
+sox_effects_global_info_t effects_global_info =
+    {sox_false, 1, &sox_global_info};
+
 void sox_output_message(FILE *file, const char *filename, const char *fmt, va_list ap)
 {
   char buffer[10];
-  char const * drivername;
+  char const * handler_name;
   char const * dot_pos;
  
-  drivername = strrchr(filename, '/');
-  if (drivername != NULL) {
-    ++drivername;
+  handler_name = strrchr(filename, '/');
+  if (handler_name != NULL) {
+    ++handler_name;
   } else {
-    drivername = strrchr(filename, '\\');
-    if (drivername != NULL)
-      ++drivername;
+    handler_name = strrchr(filename, '\\');
+    if (handler_name != NULL)
+      ++handler_name;
     else
-      drivername = filename;
+      handler_name = filename;
   }
 
-  dot_pos = strrchr(drivername, '.');
-  if (dot_pos != NULL && dot_pos - drivername <= (ptrdiff_t)(sizeof(buffer) - 1)) {
-    strncpy(buffer, drivername, (size_t)(dot_pos - drivername));
-    buffer[dot_pos - drivername] = '\0';
-    drivername = buffer;
+  dot_pos = strrchr(handler_name, '.');
+  if (dot_pos != NULL && dot_pos - handler_name <= (ptrdiff_t)(sizeof(buffer) - 1)) {
+    strncpy(buffer, handler_name, (size_t)(dot_pos - handler_name));
+    buffer[dot_pos - handler_name] = '\0';
+    handler_name = buffer;
   }
 
-  fprintf(file, "%s: ", drivername);
+  fprintf(file, "%s: ", handler_name);
   vfprintf(file, fmt, ap);
 }
 
@@ -50,7 +56,7 @@
 
 
 /* This is a bit of a hack.  It's useful to have libSoX
- * report which driver (i.e. format or effect handler) is outputing
+ * report which format or effect handler is outputing
  * the message.  Using the filename for this purpose is only an
  * approximation, but it saves a lot of work. ;)
  */
@@ -140,84 +146,73 @@
     return SOX_EFMT;
 }
 
-/*
- * Check that we have a known effect name.  If found, copy name of
- * effect into structure and place a pointer to internal data.
- * Returns -1 on error else it turns the total number of arguments
- * that should be passed to this effect's getopt() function.
- */
-int sox_geteffect_opt(eff_t effp, int argc, char **argv)
+sox_effect_handler_t const * sox_find_effect(char const * name)
 {
-    int i, optind;
+  int i;
 
-    for (i = 0; sox_effect_fns[i]; i++)
-    {
-        const sox_effect_t *e = sox_effect_fns[i]();
+  for (i = 0; sox_effect_fns[i]; ++i) {
+    const sox_effect_handler_t *e = sox_effect_fns[i] ();
+    if (e && e->name && strcasecmp(e->name, name) == 0)
+      return e;                 /* Found it. */
+  }
+  return NULL;
+}
 
-        if (e && e->name && strcasecmp(e->name, argv[0]) == 0) {
-          effp->name = e->name;
-          effp->h = e;
-          for (optind = 1; optind < argc; optind++)
-          {
-              for (i = 0; sox_effect_fns[i]; i++)
-              {
-                  const sox_effect_t *e = sox_effect_fns[i]();
-                  if (e && e->name && strcasecmp(e->name, argv[optind]) == 0)
-                    return (optind - 1);
-              }
-              /* Didn't find a match, try the next argument. */
-          }
-          /*
-           * No matches found, all the following arguments are
-           * for this effect passed in.
-           */
-          return (optind - 1);
-        }
-    }
+/* dummy effect routine for do-nothing functions */
+static int effect_nothing(sox_effect_t effp UNUSED)
+{
+  return SOX_SUCCESS;
+}
 
-    return (SOX_EOF);
+static int effect_nothing_flow(sox_effect_t effp UNUSED, const sox_ssample_t *ibuf UNUSED, sox_ssample_t *obuf UNUSED, sox_size_t *isamp, sox_size_t *osamp)
+{
+  /* Pass through samples verbatim */
+  *isamp = *osamp = min(*isamp, *osamp);
+  memcpy(obuf, ibuf, *isamp * sizeof(sox_ssample_t));
+  return SOX_SUCCESS;
 }
 
-/*
- * Check that we have a known effect name.  If found, copy name of
- * effect into structure and place a pointer to internal data.
- * Returns -1 on on failure.
- */
-
-int sox_geteffect(eff_t effp, const char *effect_name)
+static int effect_nothing_drain(sox_effect_t effp UNUSED, sox_ssample_t *obuf UNUSED, sox_size_t *osamp)
 {
-    int i;
+  /* Inform no more samples to drain */
+  *osamp = 0;
+  return SOX_EOF;
+}
 
-    memset(effp, 0, sizeof(*effp));
-
-    for(i = 0; sox_effect_fns[i]; i++) {
-        const sox_effect_t *e = sox_effect_fns[i]();
-
-        if (e && e->name && strcasecmp(e->name, effect_name) == 0) {
-          effp->name = e->name;
-          effp->h = e;
-          return SOX_SUCCESS;
-        }
-    }
-
+static int effect_nothing_getopts(sox_effect_t effp, int n, char **argv UNUSED)
+{
+#undef sox_fail
+#define sox_fail sox_message_filename=effp->handler.name,sox_fail
+  if (n) {
+    sox_fail(effp->handler.usage);
     return (SOX_EOF);
+  }
+  return (SOX_SUCCESS);
 }
 
-/*
- * Check if we have a known effect name.
- */
-sox_bool is_effect_name(char const * text)
+int sox_create_effect(sox_effect_t effp, sox_effect_handler_t const * e)
 {
-    int i;
+  memset(effp, 0, sizeof(*effp));
+  effp->global_info = &effects_global_info;
+  effp->handler = *e;
+  if (!effp->handler.getopts) effp->handler.getopts = effect_nothing_getopts;
+  if (!effp->handler.start) effp->handler.start = effect_nothing;
+  if (!effp->handler.flow) effp->handler.flow = effect_nothing_flow;
+  if (!effp->handler.drain) effp->handler.drain = effect_nothing_drain;
+  if (!effp->handler.stop) effp->handler.stop = effect_nothing;
+  if (!effp->handler.kill) effp->handler.kill = effect_nothing;
+  return SOX_SUCCESS;
+}
 
-    for(i = 0; sox_effect_fns[i]; i++) {
-        const sox_effect_t *e = sox_effect_fns[i]();
+int sox_get_effect(sox_effect_t effp, const char * name)
+{
+  sox_effect_handler_t const * e = sox_find_effect(name);
 
-        if (e && e->name && strcasecmp(e->name, text) == 0)
-          return sox_true;
-    }
+  if (!e)
+    return SOX_EOF;
 
-    return sox_false;
+  sox_create_effect(effp, e);
+  return SOX_SUCCESS;
 }
 
 /*
@@ -232,7 +227,7 @@
  * calls.
  */
 
-int sox_updateeffect(eff_t effp, const sox_signalinfo_t *in, const sox_signalinfo_t *out, 
+int sox_update_effect(sox_effect_t effp, const sox_signalinfo_t *in, const sox_signalinfo_t *out, 
                     int effect_mask)
 {
     effp->ininfo = *in;
@@ -244,7 +239,7 @@
         /* Only effects with SOX_EFF_CHAN flag can actually handle
          * outputing a different number of channels then the input.
          */
-        if (!(effp->h->flags & SOX_EFF_CHAN))
+        if (!(effp->handler.flags & SOX_EFF_CHAN))
         {
             /* If this effect is being ran before a SOX_EFF_CHAN effect
              * then effect's output is the same as the input file. Else its
@@ -264,7 +259,7 @@
         /* Only the SOX_EFF_RATE effect can handle an input that
          * is a different sample rate then the output.
          */
-        if (!(effp->h->flags & SOX_EFF_RATE))
+        if (!(effp->handler.flags & SOX_EFF_RATE))
         {
             if (effect_mask & SOX_EFF_RATE)
                 effp->ininfo.rate = out->rate;
@@ -273,9 +268,9 @@
         }
     }
 
-    if (effp->h->flags & SOX_EFF_CHAN)
+    if (effp->handler.flags & SOX_EFF_CHAN)
         effect_mask |= SOX_EFF_CHAN;
-    if (effp->h->flags & SOX_EFF_RATE)
+    if (effp->handler.flags & SOX_EFF_RATE)
         effect_mask |= SOX_EFF_RATE;
 
     return effect_mask;
--- a/src/vibro.c
+++ b/src/vibro.c
@@ -18,7 +18,7 @@
 
 #include "sox_i.h"
 
-static int getopts(eff_t effp, int n, char * * argv) 
+static int getopts(sox_effect_t effp, int n, char * * argv) 
 {
   double speed, depth = 0.5;
   char dummy;     /* To check for extraneous chars. */
@@ -29,7 +29,7 @@
       sscanf(argv[0], "%lf %c", &speed, &dummy) != 1 || speed < 0 ||
       (n > 1 && sscanf(argv[1], "%lf %c", &depth, &dummy) != 1) ||
       depth <= 0 || depth > 1) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   args[2] = argv[0];
@@ -38,13 +38,13 @@
   return sox_synth_effect_fn()->getopts(effp, array_length(args), args);
 }
 
-sox_effect_t const * sox_vibro_effect_fn(void)
+sox_effect_handler_t const * sox_vibro_effect_fn(void)
 {
-  static sox_effect_t driver;
-  driver = *sox_synth_effect_fn();
-  driver.name = "vibro";
-  driver.usage = "Usage: vibro speed [depth]";
-  driver.getopts = getopts;
-  driver.flags |= SOX_EFF_DEPRECATED;
-  return &driver;
+  static sox_effect_handler_t handler;
+  handler = *sox_synth_effect_fn();
+  handler.name = "vibro";
+  handler.usage = "Usage: vibro speed [depth]";
+  handler.getopts = getopts;
+  handler.flags |= SOX_EFF_DEPRECATED;
+  return &handler;
 }
--- a/src/vol.c
+++ b/src/vol.c
@@ -39,7 +39,7 @@
 /*
  * Process options: gain (float) type (amplitude, power, dB)
  */
-static int getopts(eff_t effp, int argc, char **argv) 
+static int getopts(sox_effect_t effp, int argc, char **argv) 
 {
   vol_t     vol = (vol_t) effp->priv; 
   char      type_string[11];
@@ -52,7 +52,7 @@
   
   /* Get the vol, and the type if it's in the same arg. */
   if (!argc || (have_type = sscanf(argv[0], "%lf %10s %c", &vol->gain, type_string, &dummy) - 1) > 1) {
-    sox_fail(effp->h->usage);
+    sox_fail(effp->handler.usage);
     return SOX_EOF;
   }
   ++argv, --argc;
@@ -67,7 +67,7 @@
   if (have_type) {
     enum_item const * p = find_enum_text(type_ptr, vol_types);
     if (!p) {
-      sox_fail(effp->h->usage);
+      sox_fail(effp->handler.usage);
       return SOX_EOF;
     }
     switch (p->value) {
@@ -80,7 +80,7 @@
 
   if (argc) {
     if (fabs(vol->gain) < 1 || sscanf(*argv, "%lf %c", &vol->limitergain, &dummy) != 1 || vol->limitergain <= 0 || vol->limitergain >= 1) {
-      sox_fail(effp->h->usage);
+      sox_fail(effp->handler.usage);
       return SOX_EOF;                  
     }
     
@@ -100,7 +100,7 @@
 /*
  * Start processing
  */
-static int start(eff_t effp)
+static int start(sox_effect_t effp)
 {
     vol_t vol = (vol_t) effp->priv;
     
@@ -116,7 +116,7 @@
 /*
  * Process data.
  */
-static int flow(eff_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
+static int flow(sox_effect_t effp, const sox_ssample_t *ibuf, sox_ssample_t *obuf, 
                 sox_size_t *isamp, sox_size_t *osamp)
 {
     vol_t vol = (vol_t) effp->priv;
@@ -174,7 +174,7 @@
     return SOX_SUCCESS;
 }
 
-static int stop(eff_t effp)
+static int stop(sox_effect_t effp)
 {
   vol_t vol = (vol_t) effp->priv;
   if (vol->limited) {
@@ -184,10 +184,10 @@
   return SOX_SUCCESS;
 }
 
-sox_effect_t const * sox_vol_effect_fn(void)
+sox_effect_handler_t const * sox_vol_effect_fn(void)
 {
-  static sox_effect_t driver = {
+  static sox_effect_handler_t handler = {
     "vol", vol_usage, SOX_EFF_MCHAN, getopts, start, flow, 0, stop, 0
   };
-  return &driver;
+  return &handler;
 }
--- a/src/vorbis.c
+++ b/src/vorbis.c
@@ -1,5 +1,5 @@
 /*
- * Ogg Vorbis sound format driver
+ * Ogg Vorbis sound format handler
  * Copyright 2001, Stan Seibert <indigo@aztec.asu.edu>
  *
  * Portions from oggenc, (c) Michael Smith <msmith@labyrinth.net.au>,
@@ -7,7 +7,7 @@
  * libvorbisfile (c) Xiphophorus Company
  *
  * May 9, 2001 - Stan Seibert (indigo@aztec.asu.edu)
- * Ogg Vorbis driver initially written.
+ * Ogg Vorbis handler initially written.
  *
  * July 5, 1991 - Skeleton file
  * Copyright 1991 Lance Norskog And Sundry Contributors
@@ -455,11 +455,11 @@
 const sox_format_t *sox_vorbis_format_fn(void)
 {
   static const char * names[] = {"vorbis", "ogg", NULL};
-  static sox_format_t driver = {
+  static sox_format_t handler = {
     names, SOX_FILE_SEEK,
     startread, read, stopread,
     startwrite, write, stopwrite,
     seek
   };
-  return &driver;
+  return &handler;
 }
--- a/src/vox-fmt.c
+++ b/src/vox-fmt.c
@@ -18,7 +18,7 @@
 const sox_format_t *sox_vox_format_fn(void)
 {
   static char const * names[] = {"vox", NULL};
-  static sox_format_t driver = {
+  static sox_format_t handler = {
     names, 0,
     sox_vox_start,
     sox_vox_read,
@@ -28,5 +28,5 @@
     sox_vox_stopwrite,
     sox_format_nothing_seek
   };
-  return &driver;
+  return &handler;
 }
--- a/src/wav.c
+++ b/src/wav.c
@@ -1,5 +1,5 @@
 /*
- * Microsoft's WAVE sound format driver
+ * Microsoft's WAVE sound format handler
  *
  * Copyright 1998-2006 Chris Bagwell and SoX Contributors
  * Copyright 1991 Lance Norskog And Sundry Contributors