shithub: sox

Download patch

ref: 3cfa08b87670abd6d5585ff9572fb3d4f3143db8
parent: 28422eb530ca46ee2e465036e6e9a2240966026f
author: robs <robs>
date: Sun Mar 30 15:53:44 EDT 2008

separate out unique LSF formats; restore priv ptrs

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -75,7 +75,15 @@
 endif (NOT HAVE_LAME_LAME_H)
 optional(HAVE_SAMPLERATE_H samplerate.h samplerate src_simple rabbit)
 optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open sndfile)
-optional(HAVE_SNDFILE_1_0_12 sndfile.h sndfile sf_open_virtual "")
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open fap)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open mat4)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open mat5)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open paf)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open pvf)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open sd2)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open w64)
+optional(HAVE_SNDFILE_H sndfile.h sndfile sf_open xi)
+optional(HAVE_SNDFILE_1_0_12 sndfile.h sndfile sf_open_virtual caf)
 optional(HAVE_SUN_AUDIOIO_H sun/audioio.h c ioctl sunaudio)
 if (NOT HAVE_SUN_AUDIOIO_H)
   optional(HAVE_SYS_AUDIOIO_H sys/audioio.h c ioctl sunaudio)
--- a/soxeffect.7
+++ b/soxeffect.7
@@ -42,6 +42,8 @@
 { } to denote those that are both optional and repeatable,
 and angle brackets < > to denote those that are repeatable but not
 optional.
+.SP
+Where applicable, default values for optional parameters are shown in parenthesis.
 .TP
 \fBallpass\fR \fIfrequency width\fR[\fBh\fR\^|\^\fBo\fR\^|\^\fBq\fR]
 Apply a two-pole all-pass filter with central frequency (in Hz)
@@ -230,7 +232,7 @@
 .B mcompand
 for a multiple-band companding effect.
 .TP
-\fBcontrast [\fIenhancement-amount\fR]
+\fBcontrast [\fIenhancement-amount (75)\fR]
 Comparable to compression, this effect modifies an audio signal to 
 make it sound louder.
 .I enhancement-amount
@@ -983,7 +985,6 @@
 [\fIpre-delay\fR (0ms) [\fIwet-gain\fR (0dB)]]]]]]
 .SP
 Add reverberation to the audio using the freeverb algorithm.
-Default values are shown in parenthesis.
 .SP
 Note that
 .B reverb
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -123,7 +123,7 @@
 libsox_fmt_vox_la_LIBADD = libsox.la
 libsox_fmt_ima_la_SOURCES = ima-fmt.c
 libsox_fmt_ima_la_LIBADD = libsox.la
-libsox_fmt_wav_la_SOURCES = adpcm.c adpcm.h ima_rw.c ima_rw.h wav.c wav.h
+libsox_fmt_wav_la_SOURCES = adpcm.c adpcm.h ima_rw.c ima_rw.h wav.c
 libsox_fmt_wav_la_LIBADD = libsox.la @GSM_LIBS@ @LIBGSM_LIBADD@
 libsox_fmt_wve_la_SOURCES = wve.c
 libsox_fmt_wve_la_LIBADD = libsox.la
@@ -143,7 +143,25 @@
 libsox_fmt_sndfile_la_SOURCES = sndfile.c
 libsox_fmt_sndfile_la_CFLAGS = @SNDFILE_CFLAGS@
 libsox_fmt_sndfile_la_LIBADD = libsox.la @SNDFILE_LIBS@
-pkglib_LTLIBRARIES += libsox_fmt_sndfile.la
+libsox_fmt_caf_la_SOURCES = caf.c
+libsox_fmt_caf_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_mat4_la_SOURCES = mat4.c
+libsox_fmt_mat4_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_mat5_la_SOURCES = mat5.c
+libsox_fmt_mat5_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_paf_la_SOURCES = paf.c
+libsox_fmt_paf_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_fap_la_SOURCES = fap.c
+libsox_fmt_fap_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_w64_la_SOURCES = w64.c
+libsox_fmt_w64_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_xi_la_SOURCES = xi.c
+libsox_fmt_xi_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_pvf_la_SOURCES = pvf.c
+libsox_fmt_pvf_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+libsox_fmt_sd2_la_SOURCES = sd2.c
+libsox_fmt_sd2_la_LIBADD = libsox.la libsox_fmt_sndfile.la 
+pkglib_LTLIBRARIES += libsox_fmt_sndfile.la libsox_fmt_caf.la libsox_fmt_mat4.la libsox_fmt_mat5.la libsox_fmt_paf.la libsox_fmt_fap.la libsox_fmt_w64.la libsox_fmt_xi.la libsox_fmt_pvf.la libsox_fmt_sd2.la
 endif
 if HAVE_AMRWB
 libsox_fmt_amr_wb_la_SOURCES = amr-wb.c amr.h amr1.h amr2.h
@@ -229,7 +247,7 @@
     lu-fmt.c 8svx.c aiff-fmt.c aifc-fmt.c au.c avr.c cdr.c cvsd-fmt.c \
     dvms-fmt.c dat.c gsm.c hcom.c htk.c lpc10.c maud.c prc.c sf.c smp.c \
     sounder.c soundtool.c sphere.c tx16w.c voc.c vox-fmt.c ima-fmt.c adpcm.c adpcm.h \
-    ima_rw.c ima_rw.h wav.c wav.h wve.c xa.c nulfile.c
+    ima_rw.c ima_rw.h wav.c wve.c xa.c nulfile.c
 libsox_la_LIBADD = @GSM_LIBS@ @LIBGSM_LIBADD@
 libsox_la_LIBADD += ../lpc10/liblpc10.la
 
@@ -247,7 +265,7 @@
     sox_LDADD += @FFMPEG_LIBS@
 endif
 if HAVE_SNDFILE
-    libsox_la_SOURCES += sndfile.c
+    libsox_la_SOURCES += sndfile.c caf.c mat4.c mat5.c paf.c fap.c w64.c xi.c pvf.c sd2.c
     libsox_la_CFLAGS += @SNDFILE_CFLAGS@
     libsox_la_LIBADD += @SNDFILE_LIBS@
     sox_LDADD += @SNDFILE_LIBS@
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -164,7 +164,7 @@
     }
     else {
         lsx_fail_errno(ft,SOX_EFMT,"ALSA driver does not support %s %u-bit output",
-                      sox_encodings_str[(unsigned char)ft->encoding.encoding], ft->encoding.bits_per_sample);
+                      sox_encodings_info[(unsigned char)ft->encoding.encoding].desc, ft->encoding.bits_per_sample);
         return SOX_EOF;
     }
     return 0;
--- a/src/amr.h
+++ b/src/amr.h
@@ -24,10 +24,10 @@
   short pcm[AMR_FRAME];
   sox_size_t pcm_index;
 } priv_t;
-#define p (*(priv_t *)ft->priv)
 
 static sox_size_t decode_1_frame(sox_format_t * ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   size_t n_1;
   UWord8 coded[AMR_CODED_MAX];
 
@@ -36,12 +36,13 @@
   n_1 = block_size[(coded[0] >> 3) & 0x0F] - 1;
   if (lsx_readbuf(ft, &coded[1], n_1) != n_1)
     return AMR_FRAME;
-  D_IF_decode(p.state, coded, p.pcm, 0);
+  D_IF_decode(p->state, coded, p->pcm, 0);
   return 0;
 }
 
 static sox_bool encode_1_frame(sox_format_t * ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   UWord8 coded[AMR_CODED_MAX];
 #include "amr1.h"
   sox_bool result = lsx_writebuf(ft, coded, (unsigned)n) == (unsigned)n;
@@ -52,10 +53,11 @@
 
 static int startread(sox_format_t * ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   char buffer[sizeof(magic) - 1];
 
-  p.pcm_index = AMR_FRAME;
-  p.state = D_IF_init();
+  p->pcm_index = AMR_FRAME;
+  p->state = D_IF_init();
 
   if (lsx_readchars(ft, buffer, sizeof(buffer)))
     return SOX_EOF;
@@ -71,14 +73,15 @@
 
 static sox_size_t read(sox_format_t * ft, sox_sample_t * buf, sox_size_t len)
 {
+  priv_t * p = (priv_t *)ft->priv;
   sox_size_t done;
 
   for (done = 0; done < len; done++) {
-    if (p.pcm_index >= AMR_FRAME)
-      p.pcm_index = decode_1_frame(ft);
-    if (p.pcm_index >= AMR_FRAME)
+    if (p->pcm_index >= AMR_FRAME)
+      p->pcm_index = decode_1_frame(ft);
+    if (p->pcm_index >= AMR_FRAME)
       break;
-    *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(p.pcm[p.pcm_index++], ft->clips);
+    *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(p->pcm[p->pcm_index++], ft->clips);
   }
   return done;
 }
@@ -85,35 +88,38 @@
 
 static int stopread(sox_format_t * ft)
 {
-  D_IF_exit(p.state);
+  priv_t * p = (priv_t *)ft->priv;
+  D_IF_exit(p->state);
   return SOX_SUCCESS;
 }
 
 static int startwrite(sox_format_t * ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   if (ft->encoding.compression != HUGE_VAL) {
-    p.mode = ft->encoding.compression;
-    if (p.mode != ft->encoding.compression || p.mode > AMR_MODE_MAX) {
+    p->mode = ft->encoding.compression;
+    if (p->mode != ft->encoding.compression || p->mode > AMR_MODE_MAX) {
       lsx_fail_errno(ft, SOX_EINVAL, "compression level must be a whole number from 0 to %i", AMR_MODE_MAX);
       return SOX_EOF;
     }
   }
-  else p.mode = 0;
+  else p->mode = 0;
 
 #include "amr2.h"
   lsx_writes(ft, magic);
-  p.pcm_index = 0;
+  p->pcm_index = 0;
   return SOX_SUCCESS;
 }
 
 static sox_size_t write(sox_format_t * ft, const sox_sample_t * buf, sox_size_t len)
 {
+  priv_t * p = (priv_t *)ft->priv;
   sox_size_t done;
 
   for (done = 0; done < len; ++done) {
-    p.pcm[p.pcm_index++] = SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
-    if (p.pcm_index == AMR_FRAME) {
-      p.pcm_index = 0;
+    p->pcm[p->pcm_index++] = SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
+    if (p->pcm_index == AMR_FRAME) {
+      p->pcm_index = 0;
       if (!encode_1_frame(ft))
         return 0;
     }
@@ -123,16 +129,17 @@
 
 static int stopwrite(sox_format_t * ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   int result = SOX_SUCCESS;
 
-  if (p.pcm_index) {
+  if (p->pcm_index) {
     do {
-      p.pcm[p.pcm_index++] = 0;
-    } while (p.pcm_index < AMR_FRAME);
+      p->pcm[p->pcm_index++] = 0;
+    } while (p->pcm_index < AMR_FRAME);
     if (!encode_1_frame(ft))
       result = SOX_EOF;
   }
-  E_IF_exit(p.state);
+  E_IF_exit(p->state);
   return result;
 }
 
--- a/src/amr1.h
+++ b/src/amr1.h
@@ -21,7 +21,7 @@
   #pragma warning(push, 1)
 #endif
 
-  int n = E_IF_encode(p.state, p.mode, p.pcm, coded, 1);
+  int n = E_IF_encode(p->state, p->mode, p->pcm, coded, 1);
 
 #if defined __SUNPRO_CC
   #pragma enable_warn
--- a/src/amr2.h
+++ b/src/amr2.h
@@ -21,7 +21,7 @@
   #pragma warning(push, 1)
 #endif
 
-  p.state = E_IF_init();
+  p->state = E_IF_init();
 
 #if defined __SUNPRO_CC
   #pragma enable_warn
--- a/src/band.h
+++ b/src/band.h
@@ -38,9 +38,9 @@
  *   Reference from the SPKit manual.
  */
 
-  p.a2 = exp(-2 * M_PI * bw_Hz / effp->in_signal.rate);
-  p.a1 = -4 * p.a2 / (1 + p.a2) * cos(2 * M_PI * p.fc / effp->in_signal.rate);
-  if (p.filter_type == filter_BPF_SPK_N)
-    p.b0 = sqrt(((1+p.a2) * (1+p.a2) - p.a1*p.a1) * (1-p.a2) / (1+p.a2));
+  p->a2 = exp(-2 * M_PI * bw_Hz / effp->in_signal.rate);
+  p->a1 = -4 * p->a2 / (1 + p->a2) * cos(2 * M_PI * p->fc / effp->in_signal.rate);
+  if (p->filter_type == filter_BPF_SPK_N)
+    p->b0 = sqrt(((1+p->a2) * (1+p->a2) - p->a1*p->a1) * (1-p->a2) / (1+p->a2));
   else
-    p.b0 = sqrt(1 - p.a1 * p.a1 / (4 * p.a2)) * (1 - p.a2);
+    p->b0 = sqrt(1 - p->a1 * p->a1 / (4 * p->a2)) * (1 - p->a2);
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -19,9 +19,7 @@
 #include <string.h>
 
 typedef biquad_t priv_t;
-#define p (*(priv_t *)effp->priv)
 
-
 static char const * const width_str[] = {
   "band-width(Hz)",
   "band-width(Hz, no warp)", /* deprecated */
@@ -36,19 +34,20 @@
     int min_args, int max_args, int fc_pos, int width_pos, int gain_pos,
     char const * allowed_width_types, filter_t filter_type)
 {
+  priv_t * p = (priv_t *)effp->priv;
   char width_type = *allowed_width_types;
   char dummy;     /* To check for extraneous chars. */
 
-  p.filter_type = filter_type;
+  p->filter_type = filter_type;
   if (n < min_args || n > max_args ||
-      (n > fc_pos    && (sscanf(argv[fc_pos], "%lf %c", &p.fc, &dummy) != 1 || p.fc <= 0)) ||
-      (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))
+      (n > fc_pos    && (sscanf(argv[fc_pos], "%lf %c", &p->fc, &dummy) != 1 || p->fc <= 0)) ||
+      (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))
     return lsx_usage(effp);
-  p.width_type = strchr(all_width_types, width_type) - all_width_types;
-  if (p.width_type >= strlen(all_width_types))
-    p.width_type = 0;
+  p->width_type = strchr(all_width_types, width_type) - all_width_types;
+  if (p->width_type >= strlen(all_width_types))
+    p->width_type = 0;
   return SOX_SUCCESS;
 }
 
@@ -55,12 +54,13 @@
 
 int sox_biquad_start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   /* Simplify: */
-  p.b2 /= p.a0;
-  p.b1 /= p.a0;
-  p.b0 /= p.a0;
-  p.a2 /= p.a0;
-  p.a1 /= p.a0;
+  p->b2 /= p->a0;
+  p->b1 /= p->a0;
+  p->b0 /= p->a0;
+  p->a2 /= p->a0;
+  p->a1 /= p->a0;
 
   if (effp->global_info->plot == sox_plot_octave) {
     printf(
@@ -76,9 +76,9 @@
       "semilogx(w,20*log10(h))\n"
       "disp('Hit return to continue')\n"
       "pause\n"
-      , effp->handler.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->in_signal.rate, effp->in_signal.rate
-      , p.b0, p.b1, p.b2, p.a1, p.a2);
+      , p->b0, p->b1, p->b2, p->a1, p->a2);
     return SOX_EOF;
   }
   if (effp->global_info->plot == sox_plot_gnuplot) {
@@ -96,12 +96,12 @@
       "set key off\n"
       "plot [f=10:Fs/2] [-35:25] 20*log10(H(f))\n"
       "pause -1 'Hit return to continue'\n"
-      , effp->handler.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->in_signal.rate, effp->in_signal.rate
-      , p.b0, p.b1, p.b2, p.a1, p.a2);
+      , p->b0, p->b1, p->b2, p->a1, p->a2);
     return SOX_EOF;
   }
-  p.o2 = p.o1 = p.i2 = p. i1 = 0;
+  p->o2 = p->o1 = p->i2 = p-> i1 = 0;
   return SOX_SUCCESS;
 }
 
@@ -109,11 +109,12 @@
 int sox_biquad_flow(sox_effect_t * effp, const sox_sample_t *ibuf,
     sox_sample_t *obuf, sox_size_t *isamp, sox_size_t *osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len = *isamp = *osamp = min(*isamp, *osamp);
   while (len--) {
-    double o0 = *ibuf*p.b0 + p.i1*p.b1 + p.i2*p.b2 - p.o1*p.a1 - p.o2*p.a2;
-    p.i2 = p.i1, p.i1 = *ibuf++;
-    p.o2 = p.o1, p.o1 = o0;
+    double o0 = *ibuf*p->b0 + p->i1*p->b1 + p->i2*p->b2 - p->o1*p->a1 - p->o2*p->a2;
+    p->i2 = p->i1, p->i1 = *ibuf++;
+    p->o2 = p->o1, p->o1 = o0;
     *obuf++ = SOX_ROUND_CLIP_COUNT(o0, effp->clips);
   }
   return SOX_SUCCESS;
--- a/src/biquads.c
+++ b/src/biquads.c
@@ -62,7 +62,6 @@
 #include <string.h>
 
 typedef biquad_t priv_t;
-#define p (*(priv_t *)effp->priv)
 
 
 static int hilo1_getopts(sox_effect_t * effp, int n, char **argv) {
@@ -72,11 +71,12 @@
 
 
 static int hilo2_getopts(sox_effect_t * effp, int n, char **argv) {
+  priv_t * p = (priv_t *)effp->priv;
   if (n != 0 && strcmp(argv[0], "-1") == 0)
     return hilo1_getopts(effp, n - 1, argv + 1);
   if (n != 0 && strcmp(argv[0], "-2") == 0)
     ++argv, --n;
-  p.width = sqrt(0.5); /* Default to Butterworth */
+  p->width = sqrt(0.5); /* Default to Butterworth */
   return sox_biquad_getopts(effp, n, argv, 1, 2, 0, 1, 2, "qoh",
       *effp->handler.name == 'l'? filter_LPF : filter_HPF);
 }
@@ -108,8 +108,9 @@
 
 
 static int tone_getopts(sox_effect_t * effp, int n, char **argv) {
-  p.width = 0.5;
-  p.fc = *effp->handler.name == 'b'? 100 : 3000;
+  priv_t * p = (priv_t *)effp->priv;
+  p->width = 0.5;
+  p->fc = *effp->handler.name == 'b'? 100 : 3000;
   return sox_biquad_getopts(effp, n, argv, 1, 3, 1, 2, 0, "shqo",
       *effp->handler.name == 'b'?  filter_lowShelf: filter_highShelf);
 }
@@ -129,9 +130,10 @@
 
 
 static int deemph_getopts(sox_effect_t * effp, int n, char **argv) {
-  p.fc    = 5283;
-  p.width = 0.4845;
-  p.gain  = -9.477;
+  priv_t * p = (priv_t *)effp->priv;
+  p->fc    = 5283;
+  p->width = 0.4845;
+  p->gain  = -9.477;
   return sox_biquad_getopts(effp, n, argv, 0, 0, 0, 1, 2, "s", filter_deemph);
 }
 
@@ -138,8 +140,9 @@
 
 static int start(sox_effect_t * effp)
 {
-  double w0 = 2 * M_PI * p.fc / effp->in_signal.rate;
-  double A  = exp(p.gain / 40 * log(10.));
+  priv_t * p = (priv_t *)effp->priv;
+  double w0 = 2 * M_PI * p->fc / effp->in_signal.rate;
+  double A  = exp(p->gain / 40 * log(10.));
   double alpha = 0;
 
   if (w0 > M_PI) {
@@ -148,105 +151,105 @@
   }
 
   /* Set defaults: */
-  p.b0 = p.b1 = p.b2 = p.a1 = p.a2 = 0;
-  p.a0 = 1;
+  p->b0 = p->b1 = p->b2 = p->a1 = p->a2 = 0;
+  p->a0 = 1;
 
-  if (p.width) switch (p.width_type) {
+  if (p->width) switch (p->width_type) {
     case width_slope:
-      alpha = sin(w0)/2 * sqrt((A + 1/A)*(1/p.width - 1) + 2);
+      alpha = sin(w0)/2 * sqrt((A + 1/A)*(1/p->width - 1) + 2);
       break;
 
     case width_Q:
-      alpha = sin(w0)/(2*p.width);
+      alpha = sin(w0)/(2*p->width);
       break;
 
     case width_bw_oct:
-      alpha = sin(w0)*sinh(log(2.)/2 * p.width * w0/sin(w0));
+      alpha = sin(w0)*sinh(log(2.)/2 * p->width * w0/sin(w0));
       break;
 
     case width_bw_Hz:
-      alpha = sin(w0)/(2*p.fc/p.width);
+      alpha = sin(w0)/(2*p->fc/p->width);
       break;
 
     case width_bw_old:
-      alpha = tan(M_PI * p.width / effp->in_signal.rate);
+      alpha = tan(M_PI * p->width / effp->in_signal.rate);
       break;
   }
-  switch (p.filter_type) {
+  switch (p->filter_type) {
     case filter_LPF: /* H(s) = 1 / (s^2 + s/Q + 1) */
-      p.b0 =  (1 - cos(w0))/2;
-      p.b1 =   1 - cos(w0);
-      p.b2 =  (1 - cos(w0))/2;
-      p.a0 =   1 + alpha;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha;
+      p->b0 =  (1 - cos(w0))/2;
+      p->b1 =   1 - cos(w0);
+      p->b2 =  (1 - cos(w0))/2;
+      p->a0 =   1 + alpha;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha;
       break;
 
     case filter_HPF: /* H(s) = s^2 / (s^2 + s/Q + 1) */
-      p.b0 =  (1 + cos(w0))/2;
-      p.b1 = -(1 + cos(w0));
-      p.b2 =  (1 + cos(w0))/2;
-      p.a0 =   1 + alpha;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha;
+      p->b0 =  (1 + cos(w0))/2;
+      p->b1 = -(1 + cos(w0));
+      p->b2 =  (1 + cos(w0))/2;
+      p->a0 =   1 + alpha;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha;
       break;
 
     case filter_BPF_CSG: /* H(s) = s / (s^2 + s/Q + 1)  (constant skirt gain, peak gain = Q) */
-      p.b0 =   sin(w0)/2;
-      p.b1 =   0;
-      p.b2 =  -sin(w0)/2;
-      p.a0 =   1 + alpha;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha;
+      p->b0 =   sin(w0)/2;
+      p->b1 =   0;
+      p->b2 =  -sin(w0)/2;
+      p->a0 =   1 + alpha;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha;
       break;
 
     case filter_BPF: /* H(s) = (s/Q) / (s^2 + s/Q + 1)      (constant 0 dB peak gain) */
-      p.b0 =   alpha;
-      p.b1 =   0;
-      p.b2 =  -alpha;
-      p.a0 =   1 + alpha;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha;
+      p->b0 =   alpha;
+      p->b1 =   0;
+      p->b2 =  -alpha;
+      p->a0 =   1 + alpha;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha;
       break;
 
     case filter_notch: /* H(s) = (s^2 + 1) / (s^2 + s/Q + 1) */
-      p.b0 =   1;
-      p.b1 =  -2*cos(w0);
-      p.b2 =   1;
-      p.a0 =   1 + alpha;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha;
+      p->b0 =   1;
+      p->b1 =  -2*cos(w0);
+      p->b2 =   1;
+      p->a0 =   1 + alpha;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha;
       break;
 
     case filter_APF: /* H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) */
-      p.b0 =   1 - alpha;
-      p.b1 =  -2*cos(w0);
-      p.b2 =   1 + alpha;
-      p.a0 =   1 + alpha;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha;
+      p->b0 =   1 - alpha;
+      p->b1 =  -2*cos(w0);
+      p->b2 =   1 + alpha;
+      p->a0 =   1 + alpha;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha;
       break;
 
     case filter_peakingEQ: /* H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) */
       if (A == 1)
         return SOX_EFF_NULL;
-      p.b0 =   1 + alpha*A;
-      p.b1 =  -2*cos(w0);
-      p.b2 =   1 - alpha*A;
-      p.a0 =   1 + alpha/A;
-      p.a1 =  -2*cos(w0);
-      p.a2 =   1 - alpha/A;
+      p->b0 =   1 + alpha*A;
+      p->b1 =  -2*cos(w0);
+      p->b2 =   1 - alpha*A;
+      p->a0 =   1 + alpha/A;
+      p->a1 =  -2*cos(w0);
+      p->a2 =   1 - alpha/A;
       break;
 
     case filter_lowShelf: /* H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) */
       if (A == 1)
         return SOX_EFF_NULL;
-      p.b0 =    A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
-      p.b1 =  2*A*( (A-1) - (A+1)*cos(w0)                   );
-      p.b2 =    A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
-      p.a0 =        (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha;
-      p.a1 =   -2*( (A-1) + (A+1)*cos(w0)                   );
-      p.a2 =        (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha;
+      p->b0 =    A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
+      p->b1 =  2*A*( (A-1) - (A+1)*cos(w0)                   );
+      p->b2 =    A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
+      p->a0 =        (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha;
+      p->a1 =   -2*( (A-1) + (A+1)*cos(w0)                   );
+      p->a2 =        (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha;
       break;
 
     case filter_deemph:  /* See deemph.plt for documentation */
@@ -259,49 +262,49 @@
     case filter_highShelf: /* H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) */
       if (!A)
         return SOX_EFF_NULL;
-      p.b0 =    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
-      p.b1 = -2*A*( (A-1) + (A+1)*cos(w0)                   );
-      p.b2 =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
-      p.a0 =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
-      p.a1 =    2*( (A-1) - (A+1)*cos(w0)                   );
-      p.a2 =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
+      p->b0 =    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
+      p->b1 = -2*A*( (A-1) + (A+1)*cos(w0)                   );
+      p->b2 =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
+      p->a0 =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
+      p->a1 =    2*( (A-1) - (A+1)*cos(w0)                   );
+      p->a2 =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
       break;
 
     case filter_LPF_1: /* single-pole */
-      p.a1 = -exp(-w0);
-      p.b0 = 1 + p.a1;
+      p->a1 = -exp(-w0);
+      p->b0 = 1 + p->a1;
       break;
 
     case filter_HPF_1: /* single-pole */
-      p.a1 = -exp(-w0);
-      p.b0 = (1 - p.a1)/2;
-      p.b1 = -p.b0;
+      p->a1 = -exp(-w0);
+      p->b0 = (1 - p->a1)/2;
+      p->b1 = -p->b0;
       break;
 
     case filter_BPF_SPK: case filter_BPF_SPK_N: {
       double bw_Hz;
-      if (!p.width)
-        p.width = p.fc / 2;
-      bw_Hz = p.width_type == width_Q?  p.fc / p.width :
-        p.width_type == width_bw_Hz? p.width :
-        p.fc * (pow(2., p.width) - 1) * pow(2., -0.5 * p.width); /* bw_oct */
+      if (!p->width)
+        p->width = p->fc / 2;
+      bw_Hz = p->width_type == width_Q?  p->fc / p->width :
+        p->width_type == width_bw_Hz? p->width :
+        p->fc * (pow(2., p->width) - 1) * pow(2., -0.5 * p->width); /* bw_oct */
       #include "band.h" /* Has different licence */
       break;
     }
 
     case filter_AP1:     /* Experimental 1-pole all-pass from Tom Erbe @ UCSD */
-      p.b0 = exp(-w0);
-      p.b1 = -1;
-      p.a1 = -exp(-w0);
+      p->b0 = exp(-w0);
+      p->b1 = -1;
+      p->a1 = -exp(-w0);
       break;
 
     case filter_AP2:     /* Experimental 2-pole all-pass from Tom Erbe @ UCSD */
-      p.b0 = 1 - sin(w0);
-      p.b1 = -2 * cos(w0);
-      p.b2 = 1 + sin(w0);
-      p.a0 = 1 + sin(w0);
-      p.a1 = -2 * cos(w0);
-      p.a2 = 1 - sin(w0);
+      p->b0 = 1 - sin(w0);
+      p->b1 = -2 * cos(w0);
+      p->b2 = 1 + sin(w0);
+      p->a0 = 1 + sin(w0);
+      p->a1 = -2 * cos(w0);
+      p->a2 = 1 - sin(w0);
       break;
   }
   return sox_biquad_start(effp);
--- /dev/null
+++ b/src/caf.c
@@ -1,0 +1,39 @@
+/* libSoX file format: CAF   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_1_0_12
+
+SOX_FORMAT_HANDLER(caf)
+{
+  static char const * const names[] = {"caf", NULL};
+  static unsigned const write_encodings[] = {
+    SOX_ENCODING_SIGN2, 16, 24, 32, 8, 0,
+    SOX_ENCODING_FLOAT, 32, 64, 0,
+    SOX_ENCODING_ALAW, 8, 0,
+    SOX_ENCODING_ULAW, 8, 0,
+    0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Apples's Core Audio Format";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- a/src/contrast.c
+++ b/src/contrast.c
@@ -18,10 +18,10 @@
 #include "sox_i.h"
 
 typedef struct {double contrast;} priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int create(sox_effect_t * effp, int argc, char * * argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   p->contrast = 75;
   do {NUMERIC_PARAMETER(contrast, 0, 100)} while (0);
   p->contrast /= 750; /* shift range to 0 to 0.1333, default 0.1 */
@@ -31,6 +31,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len = *isamp = *osamp = min(*isamp, *osamp);
   while (len--) {
     double d = *ibuf++ * (-M_PI_2 / SOX_SAMPLE_MIN);
--- a/src/delay.c
+++ b/src/delay.c
@@ -24,10 +24,10 @@
   sox_size_t delay, pad, buffer_size, buffer_index;
   sox_sample_t * buffer;
 } priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int kill(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i;
 
   for (i = 0; i < p->argc; ++i)
@@ -38,6 +38,7 @@
 
 static int create(sox_effect_t * effp, int argc, char * * argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t delay, max_samples = 0;
   unsigned i;
 
@@ -58,6 +59,7 @@
 
 static int stop(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   free(p->buffer);
   return SOX_SUCCESS;
 }
@@ -64,6 +66,7 @@
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t max_delay;
 
   if (!p->max_arg)
@@ -80,6 +83,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len = *isamp = *osamp = min(*isamp, *osamp);
 
   if (!p->buffer_size)
@@ -99,6 +103,7 @@
 
 static int drain(sox_effect_t * effp, sox_sample_t * obuf, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len = *osamp = min(p->delay + p->pad, *osamp);
 
   for (; p->delay && len; --p->delay, --len) {
--- a/src/dither.c
+++ b/src/dither.c
@@ -14,10 +14,10 @@
 #include "sox_i.h"
 
 typedef struct {double amount;} priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int getopts(sox_effect_t * effp, int argc, char * * argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   p->amount = M_SQRT2;   /* Default to half a bit. */
   do {NUMERIC_PARAMETER(amount, 1, 10)} while (0);
   return argc?  lsx_usage(effp) : SOX_SUCCESS;
@@ -25,6 +25,7 @@
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (effp->out_signal.precision > 16)
     return SOX_EFF_NULL;   /* Dithering not needed at >= 24 bits */
   p->amount *= 1 << (16 - effp->out_signal.precision);
@@ -34,6 +35,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len = *isamp = *osamp = min(*isamp, *osamp);
 
   while (len--) {   /* 16 signed bits of triangular noise: */
--- a/src/earwax.c
+++ b/src/earwax.c
@@ -53,15 +53,15 @@
 
 #define NUMTAPS array_length(filt)
 typedef struct {sox_sample_t tap[NUMTAPS];} priv_t; /* FIR filter z^-1 delays */
-#define p (*(priv_t *)effp->priv)
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (effp->in_signal.rate != 44100 || effp->in_signal.channels != 2) {
     sox_fail("works only with stereo audio sampled at 44100Hz (i.e. CDDA)");
     return SOX_EOF;
   }
-  memset(p.tap, 0, NUMTAPS * sizeof(*p.tap)); /* zero tap memory */
+  memset(p->tap, 0, NUMTAPS * sizeof(*p->tap)); /* zero tap memory */
   return SOX_SUCCESS;
 }
 
@@ -68,6 +68,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
                 sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t i, len = *isamp = *osamp = min(*isamp, *osamp);
 
   while (len--) {       /* update taps and calculate output */
@@ -74,11 +75,11 @@
     sox_sample_t output = 0;
 
     for (i = NUMTAPS - 1; i; --i) {
-      p.tap[i] = p.tap[i - 1];
-      output += p.tap[i] * filt[i];
+      p->tap[i] = p->tap[i - 1];
+      output += p->tap[i] * filt[i];
     }
-    p.tap[0] = *ibuf++ / 64;
-    *obuf++ = output + p.tap[0] * filt[0];   /* store scaled output */
+    p->tap[0] = *ibuf++ / 64;
+    *obuf++ = output + p->tap[0] * filt[0];   /* store scaled output */
   }
   return SOX_SUCCESS;
 }
--- /dev/null
+++ b/src/fap.c
@@ -1,0 +1,35 @@
+/* libSoX file format: FAP   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(fap)
+{
+  static char const * const names[] = {"fap", NULL};
+  static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 24, 16, 8,0,0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description =
+    "Ensoniq PARIS digitial audio editing system (little endian)";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- a/src/flac.c
+++ b/src/flac.c
@@ -67,7 +67,6 @@
   FLAC__StreamMetadata * metadata[2];
   unsigned num_metadata;
 } priv_t;
-#define p ((priv_t *)ft->priv)
 
 
 
@@ -74,6 +73,7 @@
 static void FLAC__decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FLAC__StreamMetadata const * const metadata, void * const client_data)
 {
   sox_format_t * ft = (sox_format_t *) client_data;
+  priv_t * p = (priv_t *)ft->priv;
 
   (void) flac;
 
@@ -115,6 +115,7 @@
 static FLAC__StreamDecoderWriteStatus FLAC__frame_decode_callback(FLAC__StreamDecoder const * const flac, FLAC__Frame const * const frame, FLAC__int32 const * const buffer[], void * const client_data)
 {
   sox_format_t * ft = (sox_format_t *) client_data;
+  priv_t * p = (priv_t *)ft->priv;
 
   (void) flac;
 
@@ -133,6 +134,7 @@
 
 static int start_read(sox_format_t * const ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   sox_debug("API version %u", FLAC_API_VERSION_CURRENT);
   p->decoder = FLAC__stream_decoder_new();
   if (p->decoder == NULL) {
@@ -189,6 +191,7 @@
 
 static sox_size_t read_samples(sox_format_t * const ft, sox_sample_t * sampleBuffer, sox_size_t const requested)
 {
+  priv_t * p = (priv_t *)ft->priv;
   size_t actual = 0;
 
   while (!p->eof && actual < requested) {
@@ -218,6 +221,7 @@
 
 static int stop_read(sox_format_t * const ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   if (!FLAC__stream_decoder_finish(p->decoder) && p->eof)
     sox_warn("decoder MD5 checksum mismatch.");
   FLAC__stream_decoder_delete(p->decoder);
@@ -278,6 +282,7 @@
 
 static int start_write(sox_format_t * const ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   FLAC__StreamEncoderState status;
   unsigned compression_level = MAX_COMPRESSION; /* Default to "best" */
 
@@ -427,6 +432,7 @@
 
 static sox_size_t write_samples(sox_format_t * const ft, sox_sample_t const * const sampleBuffer, sox_size_t const len)
 {
+  priv_t * p = (priv_t *)ft->priv;
   unsigned i;
 
   for (i = 0; i < len; ++i) {
@@ -456,6 +462,7 @@
 
 static int stop_write(sox_format_t * const ft)
 {
+  priv_t * p = (priv_t *)ft->priv;
   FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(p->encoder);
   unsigned i;
 
@@ -479,6 +486,7 @@
  */
 static int seek(sox_format_t * ft, sox_size_t offset)
 {
+  priv_t * p = (priv_t *)ft->priv;
   int result = ft->mode == 'r' && FLAC__stream_decoder_seek_absolute(p->decoder, (FLAC__uint64)(offset / ft->signal.channels)) ?  SOX_SUCCESS : SOX_EOF;
   p->wide_sample_number = p->number_of_wide_samples = 0;
   return result;
--- a/src/formats.c
+++ b/src/formats.c
@@ -33,70 +33,6 @@
   #include <io.h>
 #endif
 
-const char * const sox_encodings_str[] = {
-  "?",
-  "Signed Integer PCM",
-  "Unsigned Integer PCM",
-  "Floating Point PCM",
-  "Floating Point (text) PCM",
-  "FLAC",
-  "HCOM",
-  "WavPack",
-  "Floating Point WavPack",
-  "", /* Lossless above, lossy below */
-  "u-law",
-  "A-law",
-  "G.721 ADPCM",
-  "G.723 ADPCM",
-  "CL ADPCM (from 8-bit)",
-  "CL ADPCM (from 16-bit)",
-  "MS ADPCM",
-  "IMA ADPCM",
-  "OKI ADPCM",
-  "GSM",
-  "MPEG audio (layer I, II or III)",
-  "Vorbis",
-  "AMR-WB",
-  "AMR-NB",
-  "CVSD",
-  "LPC10",
-};
-
-assert_static(array_length(sox_encodings_str) == SOX_ENCODINGS,
-    SIZE_MISMATCH_BETWEEN_sox_encodings_t_AND_sox_encodings_str);
-
-const char * const sox_encodings_short_str[] = {
-  "n/a",
-  "Signed PCM",
-  "Unsigned PCM",
-  "F.P. PCM",
-  "F.P. PCM",
-  "FLAC",
-  "HCOM",
-  "WavPack",
-  "F.P. WavPack",
-  "", /* Lossless above, lossy below */
-  "u-law",
-  "A-law",
-  "G.721 ADPCM",
-  "G.723 ADPCM",
-  "CL ADPCM (8)",
-  "CL ADPCM (16)",
-  "MS ADPCM",
-  "IMA ADPCM",
-  "OKI ADPCM",
-  "GSM",
-  "MPEG audio",
-  "Vorbis",
-  "AMR-WB",
-  "AMR-NB",
-  "CVSD",
-  "LPC10",
-};
-
-assert_static(array_length(sox_encodings_short_str) == SOX_ENCODINGS,
-    SIZE_MISMATCH_BETWEEN_sox_encodings_t_AND_sox_encodings_short_str);
-
 static char const * detect_magic(sox_format_t * ft, char const * ext)
 {
   char data[256];
@@ -147,9 +83,45 @@
   return NULL;
 }
 
+sox_encodings_info_t const sox_encodings_info[] = {
+  {0         , "n/a"          , "Unknown or not applicable"},
+  {0         , "Signed PCM"   , "Signed Integer PCM"},
+  {0         , "Unsigned PCM" , "Unsigned Integer PCM"},
+  {0         , "F.P. PCM"     , "Floating Point PCM"},
+  {0         , "F.P. PCM"     , "Floating Point (text) PCM"},
+  {0         , "FLAC"         , "FLAC"},
+  {0         , "HCOM"         , "HCOM"},
+  {0         , "WavPack"      , "WavPack"},
+  {0         , "F.P. WavPack" , "Floating Point WavPack"},
+  {SOX_LOSSY1, "u-law"        , "u-law"},
+  {SOX_LOSSY1, "A-law"        , "A-law"},
+  {SOX_LOSSY1, "G.721 ADPCM"  , "G.721 ADPCM"},
+  {SOX_LOSSY1, "G.723 ADPCM"  , "G.723 ADPCM"},
+  {SOX_LOSSY1, "CL ADPCM (8)" , "CL ADPCM (from 8-bit)"},
+  {SOX_LOSSY1, "CL ADPCM (16)", "CL ADPCM (from 16-bit)"},
+  {SOX_LOSSY1, "MS ADPCM"     , "MS ADPCM"},
+  {SOX_LOSSY1, "IMA ADPCM"    , "IMA ADPCM"},
+  {SOX_LOSSY1, "OKI ADPCM"    , "OKI ADPCM"},
+  {SOX_LOSSY1, "DPCM"         , "DPCM"},
+  {0         , "DWVW"         , "DWVW"},
+  {0         , "DWVWN"        , "DWVWN"},
+  {SOX_LOSSY2, "GSM"          , "GSM"},
+  {SOX_LOSSY2, "MPEG audio"   , "MPEG audio (layer I, II or III)"},
+  {SOX_LOSSY2, "Vorbis"       , "Vorbis"},
+  {SOX_LOSSY2, "AMR-WB"       , "AMR-WB"},
+  {SOX_LOSSY2, "AMR-NB"       , "AMR-NB"},
+  {SOX_LOSSY2, "CVSD"         , "CVSD"},
+  {SOX_LOSSY2, "LPC10"        , "LPC10"},
+};
+
+assert_static(array_length(sox_encodings_info) == SOX_ENCODINGS,
+    SIZE_MISMATCH_BETWEEN_sox_encodings_t_AND_sox_encodings_info);
+
 unsigned sox_precision(sox_encoding_t encoding, unsigned bits_per_sample)
 {
   switch (encoding) {
+    case SOX_ENCODING_DWVW:       return bits_per_sample;
+    case SOX_ENCODING_DWVWN:      return !bits_per_sample? 16: 0; /* ? */
     case SOX_ENCODING_HCOM:       return !(bits_per_sample & 7) && (bits_per_sample >> 3) - 1 < 1? bits_per_sample: 0;
     case SOX_ENCODING_WAVPACK:
     case SOX_ENCODING_FLAC:       return !(bits_per_sample & 7) && (bits_per_sample >> 3) - 1 < 4? bits_per_sample: 0;
@@ -168,6 +140,7 @@
     case SOX_ENCODING_G723:       return bits_per_sample == 3? 8:
                                          bits_per_sample == 5? 14: 0;
     case SOX_ENCODING_CVSD:       return bits_per_sample == 1? 16: 0;
+    case SOX_ENCODING_DPCM:       return bits_per_sample; /* ? */
 
     case SOX_ENCODING_GSM:
     case SOX_ENCODING_MP3:
@@ -181,7 +154,6 @@
     case SOX_ENCODING_FLOAT_TEXT: return !bits_per_sample? 53: 0;
 
     case SOX_ENCODINGS:
-    case SOX_ENCODING_LOSSLESS:
     case SOX_ENCODING_UNKNOWN:    break;
   }
   return 0;
@@ -584,7 +556,7 @@
       while (enc_arg(unsigned));
     }
     if (e != ft->encoding.encoding) {
-      sox_warn("%s can't encode %s", ft->handler.names[0], sox_encodings_str[ft->encoding.encoding]);
+      sox_warn("%s can't encode %s", ft->handler.names[0], sox_encodings_info[ft->encoding.encoding].desc);
       ft->encoding.encoding = 0;
     }
     else {
@@ -612,7 +584,7 @@
       if (given_size) {
         if (found)
           ft->encoding.bits_per_sample = given_size;
-        else sox_warn("%s can't encode %s to %u-bit", ft->handler.names[0], sox_encodings_str[ft->encoding.encoding], given_size);
+        else sox_warn("%s can't encode %s to %u-bit", ft->handler.names[0], sox_encodings_info[ft->encoding.encoding].desc, given_size);
       }
     }
   }
@@ -636,7 +608,7 @@
     i = 0;
     while ((e = enc_arg(sox_encoding_t)))
       while ((s = enc_arg(unsigned)))
-        if (e < SOX_ENCODING_LOSSLESS &&
+        if (!(sox_encodings_info[e].flags & (SOX_LOSSY1 | SOX_LOSSY2)) &&
             sox_precision(e, s) >= ft->signal.precision && s < ft->encoding.bits_per_sample) {
           ft->encoding.encoding = e;
           ft->encoding.bits_per_sample = s;
--- a/src/formats.h
+++ b/src/formats.h
@@ -1,4 +1,6 @@
-/* This library is free software; you can redistribute it and/or modify it
+/* libSoX static formats list   (c) 2006-8 Chris Bagwell and SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation; either version 2.1 of the License, or (at
  * your option) any later version.
@@ -83,6 +85,17 @@
 #endif
 #if defined HAVE_SNDFILE_H
   FORMAT(sndfile)
+  #if defined HAVE_SNDFILE_1_0_12
+  FORMAT(caf)
+  #endif
+  FORMAT(fap)
+  FORMAT(mat4)
+  FORMAT(mat5)
+  FORMAT(paf)
+  FORMAT(pvf)
+  FORMAT(sd2)
+  FORMAT(w64)
+  FORMAT(xi)
 #endif
 #if defined(HAVE_SYS_AUDIOIO_H) || defined(HAVE_SUN_AUDIOIO_H)
   FORMAT(sunau)
--- /dev/null
+++ b/src/mat4.c
@@ -1,0 +1,37 @@
+/* libSoX file format: MatLab4   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(mat4)
+{
+  static char const * const names[] = {"mat4", "mat", NULL};
+  static unsigned const write_encodings[] = {
+    SOX_ENCODING_SIGN2, 16, 32, 0,
+    SOX_ENCODING_FLOAT, 32, 64, 0,
+    0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Gnu Octave 2.0 format";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- /dev/null
+++ b/src/mat5.c
@@ -1,0 +1,37 @@
+/* libSoX file format: MatLab5   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(mat5)
+{
+  static char const * const names[] = {"mat5", NULL};
+  static unsigned const write_encodings[] = {
+    SOX_ENCODING_SIGN2, 16, 32, 0,
+    SOX_ENCODING_FLOAT, 32, 64, 0,
+    0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Gnu Octave 2.1 format";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- a/src/normalise.c
+++ b/src/normalise.c
@@ -25,10 +25,10 @@
   sox_sample_t  min, max;
   FILE          * tmp_file;
 } priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int create(sox_effect_t * effp, int argc, char * * argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (argc && !strcmp(*argv, "-i")) p->individual = sox_true, ++argv, --argc;
   do {NUMERIC_PARAMETER(level, -100, 0)} while (0);
   p->level = dB_to_linear(p->level);
@@ -37,6 +37,7 @@
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (!p->individual)
     effp->flows = 1;
   p->norm0 = p->max = p->min = 0;
@@ -51,6 +52,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len;
 
   if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
@@ -67,6 +69,7 @@
 
 static int drain(sox_effect_t * effp, sox_sample_t * obuf, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t len;
   int result = SOX_SUCCESS;
 
@@ -87,6 +90,7 @@
 
 static int stop(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   fclose(p->tmp_file); /* auto-deleted by tmpfile */
   return SOX_SUCCESS;
 }
--- a/src/pad.c
+++ b/src/pad.c
@@ -29,28 +29,28 @@
   unsigned pads_pos;  /* Number of pads completed so far */
   sox_size_t pad_pos; /* Number of samples through the current pad */
 } priv_t;
-#define p (*(priv_t *)effp->priv)
 
 static int parse(sox_effect_t * effp, char * * argv, sox_rate_t rate)
 {
+  priv_t * p = (priv_t *)effp->priv;
   char const * next;
   unsigned i;
 
-  for (i = 0; i < p.npads; ++i) {
+  for (i = 0; i < p->npads; ++i) {
     if (argv) /* 1st parse only */
-      p.pads[i].str = lsx_strdup(argv[i]);
-    next = lsx_parsesamples(rate, p.pads[i].str, &p.pads[i].pad, 't');
+      p->pads[i].str = lsx_strdup(argv[i]);
+    next = lsx_parsesamples(rate, p->pads[i].str, &p->pads[i].pad, 't');
     if (next == NULL) break;
     if (*next == '\0')
-      p.pads[i].start = i? SOX_SIZE_MAX : 0;
+      p->pads[i].start = i? SOX_SIZE_MAX : 0;
     else {
       if (*next != '@') break;
-      next = lsx_parsesamples(rate, next+1, &p.pads[i].start, 't');
+      next = lsx_parsesamples(rate, next+1, &p->pads[i].start, 't');
       if (next == NULL || *next != '\0') break;
     }
-    if (i > 0 && p.pads[i].start <= p.pads[i-1].start) break;
+    if (i > 0 && p->pads[i].start <= p->pads[i-1].start) break;
   }
-  if (i < p.npads)
+  if (i < p->npads)
     return lsx_usage(effp);
   return SOX_SUCCESS;
 }
@@ -57,25 +57,28 @@
 
 static int create(sox_effect_t * effp, int n, char * * argv)
 {
-  p.pads = lsx_calloc(p.npads = n, sizeof(*p.pads));
+  priv_t * p = (priv_t *)effp->priv;
+  p->pads = lsx_calloc(p->npads = n, sizeof(*p->pads));
   return parse(effp, argv, 96000.); /* No rate yet; parse with dummy */
 }
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i;
 
   parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
-  p.in_pos = p.pad_pos = p.pads_pos = 0;
-  for (i = 0; i < p.npads; ++i)
-    if (p.pads[i].pad)
+  p->in_pos = p->pad_pos = p->pads_pos = 0;
+  for (i = 0; i < p->npads; ++i)
+    if (p->pads[i].pad)
       return SOX_SUCCESS;
   return SOX_EFF_NULL;
 }
 
-static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, sox_sample_t * obuf,
-                sox_size_t * isamp, sox_size_t * osamp)
+static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
+    sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t c, idone = 0, odone = 0;
   *isamp /= effp->in_signal.channels;
   *osamp /= effp->in_signal.channels;
@@ -82,16 +85,16 @@
 
   do {
     /* Copying: */
-    for (; idone < *isamp && odone < *osamp && !(p.pads_pos != p.npads && p.in_pos == p.pads[p.pads_pos].start); ++idone, ++odone, ++p.in_pos)
+    for (; idone < *isamp && odone < *osamp && !(p->pads_pos != p->npads && p->in_pos == p->pads[p->pads_pos].start); ++idone, ++odone, ++p->in_pos)
       for (c = 0; c < effp->in_signal.channels; ++c) *obuf++ = *ibuf++;
 
     /* Padding: */
-    if (p.pads_pos != p.npads && p.in_pos == p.pads[p.pads_pos].start) {
-      for (; odone < *osamp && p.pad_pos < p.pads[p.pads_pos].pad; ++odone, ++p.pad_pos)
+    if (p->pads_pos != p->npads && p->in_pos == p->pads[p->pads_pos].start) {
+      for (; odone < *osamp && p->pad_pos < p->pads[p->pads_pos].pad; ++odone, ++p->pad_pos)
         for (c = 0; c < effp->in_signal.channels; ++c) *obuf++ = 0;
-      if (p.pad_pos == p.pads[p.pads_pos].pad) { /* Move to next pad? */
-        ++p.pads_pos;
-        p.pad_pos = 0;
+      if (p->pad_pos == p->pads[p->pads_pos].pad) { /* Move to next pad? */
+        ++p->pads_pos;
+        p->pad_pos = 0;
       }
     }
   } while (idone < *isamp && odone < *osamp);
@@ -103,25 +106,28 @@
 
 static int drain(sox_effect_t * effp, sox_sample_t * obuf, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   static sox_size_t isamp = 0;
-  if (p.pads_pos != p.npads && p.in_pos != p.pads[p.pads_pos].start)
-    p.in_pos = SOX_SIZE_MAX;  /* Invoke the final pad (with no given start) */
+  if (p->pads_pos != p->npads && p->in_pos != p->pads[p->pads_pos].start)
+    p->in_pos = SOX_SIZE_MAX;  /* Invoke the final pad (with no given start) */
   return flow(effp, 0, obuf, &isamp, osamp);
 }
 
 static int stop(sox_effect_t * effp)
 {
-  if (p.pads_pos != p.npads)
-    sox_warn("Input audio too short; pads not applied: %u", p.npads-p.pads_pos);
+  priv_t * p = (priv_t *)effp->priv;
+  if (p->pads_pos != p->npads)
+    sox_warn("Input audio too short; pads not applied: %u", p->npads-p->pads_pos);
   return SOX_SUCCESS;
 }
 
 static int kill(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i;
-  for (i = 0; i < p.npads; ++i)
-    free(p.pads[i].str);
-  free(p.pads);
+  for (i = 0; i < p->npads; ++i)
+    free(p->pads[i].str);
+  free(p->pads);
   return SOX_SUCCESS;
 }
 
--- /dev/null
+++ b/src/paf.c
@@ -1,0 +1,35 @@
+/* libSoX file format: PAF   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(paf)
+{
+  static char const * const names[] = {"paf", NULL};
+  static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 24, 16, 8,0,0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description =
+    "Ensoniq PARIS digitial audio editing system (big endian)";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- /dev/null
+++ b/src/pvf.c
@@ -1,0 +1,34 @@
+/* libSoX file format: PVF   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(pvf)
+{
+  static char const * const names[] = {"pvf", NULL};
+  static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 32, 16, 8,0,0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Portable Voice Format";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- a/src/remix.c
+++ b/src/remix.c
@@ -30,7 +30,6 @@
     } * in_specs;
   } * out_specs;
 } priv_t;
-#define p (*(priv_t *)effp->priv)
 
 #define PARSE(SEP, SCAN, VAR, MIN, SEPARATORS) do {\
   end = strpbrk(text, SEPARATORS); \
@@ -47,15 +46,16 @@
 
 static int parse(sox_effect_t * effp, char * * argv, unsigned channels)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i, j;
 
-  p.min_in_channels = 0;
-  for (i = 0; i < p.num_out_channels; ++i) {
+  p->min_in_channels = 0;
+  for (i = 0; i < p->num_out_channels; ++i) {
     sox_bool mul_spec = sox_false;
     char * text, * end;
     if (argv) /* 1st parse only */
-      p.out_specs[i].str = lsx_strdup(argv[i]);
-    for (j = 0, text = p.out_specs[i].str; *text;) {
+      p->out_specs[i].str = lsx_strdup(argv[i]);
+    for (j = 0, text = p->out_specs[i].str; *text;) {
       static char const separators[] = "-vpi,";
       char sep1, sep2;
       int chan1 = 1, chan2 = channels, n;
@@ -78,35 +78,37 @@
         mul_spec = sox_true;
       }
       if (chan2 < chan1) {int t = chan1; chan1 = chan2; chan2 = t;}
-      p.out_specs[i].in_specs = lsx_realloc(p.out_specs[i].in_specs,
-          (j + chan2 - chan1 + 1) * sizeof(*p.out_specs[i].in_specs));
+      p->out_specs[i].in_specs = lsx_realloc(p->out_specs[i].in_specs,
+          (j + chan2 - chan1 + 1) * sizeof(*p->out_specs[i].in_specs));
       while (chan1 <= chan2) {
-        p.out_specs[i].in_specs[j].channel_num = chan1++ - 1;
-        p.out_specs[i].in_specs[j++].multiplier = multiplier;
+        p->out_specs[i].in_specs[j].channel_num = chan1++ - 1;
+        p->out_specs[i].in_specs[j++].multiplier = multiplier;
       }
-      p.min_in_channels = max(p.min_in_channels, (unsigned)chan2);
+      p->min_in_channels = max(p->min_in_channels, (unsigned)chan2);
     }
-    p.out_specs[i].num_in_channels = j;
-    for (j = 0; j < p.out_specs[i].num_in_channels; ++j)
-      if (p.out_specs[i].in_specs[j].multiplier == HUGE_VAL)
-        p.out_specs[i].in_specs[j].multiplier = (p.mode == automatic || (p.mode == semi && !mul_spec)) ?  1. / p.out_specs[i].num_in_channels : 1;
+    p->out_specs[i].num_in_channels = j;
+    for (j = 0; j < p->out_specs[i].num_in_channels; ++j)
+      if (p->out_specs[i].in_specs[j].multiplier == HUGE_VAL)
+        p->out_specs[i].in_specs[j].multiplier = (p->mode == automatic || (p->mode == semi && !mul_spec)) ?  1. / p->out_specs[i].num_in_channels : 1;
   }
-  effp->out_signal.channels = p.num_out_channels;
+  effp->out_signal.channels = p->num_out_channels;
   return SOX_SUCCESS;
 }
 
 static int create(sox_effect_t * effp, int argc, char * * argv)
 {
-  if (argc && !strcmp(*argv, "-m")) p.mode = manual   , ++argv, --argc;
-  if (argc && !strcmp(*argv, "-a")) p.mode = automatic, ++argv, --argc;
-  p.out_specs = lsx_calloc(p.num_out_channels = argc, sizeof(*p.out_specs));
+  priv_t * p = (priv_t *)effp->priv;
+  if (argc && !strcmp(*argv, "-m")) p->mode = manual   , ++argv, --argc;
+  if (argc && !strcmp(*argv, "-a")) p->mode = automatic, ++argv, --argc;
+  p->out_specs = lsx_calloc(p->num_out_channels = argc, sizeof(*p->out_specs));
   return parse(effp, argv, 1); /* No channels yet; parse with dummy */
 }
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   parse(effp, NULL, effp->in_signal.channels);
-  if (effp->in_signal.channels < p.min_in_channels) {
+  if (effp->in_signal.channels < p->min_in_channels) {
     sox_fail("too few input channels");
     return SOX_EOF;
   }
@@ -116,6 +118,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i, j, len;
   len =  min(*isamp / effp->in_signal.channels, *osamp / effp->out_signal.channels);
   *isamp = len * effp->in_signal.channels;
@@ -123,8 +126,8 @@
 
   for (; len--; ibuf += effp->in_signal.channels) for (j = 0; j < effp->out_signal.channels; j++) {
     double out = 0;
-    for (i = 0; i < p.out_specs[j].num_in_channels; i++)
-      out += ibuf[p.out_specs[j].in_specs[i].channel_num] * p.out_specs[j].in_specs[i].multiplier;
+    for (i = 0; i < p->out_specs[j].num_in_channels; i++)
+      out += ibuf[p->out_specs[j].in_specs[i].channel_num] * p->out_specs[j].in_specs[i].multiplier;
     *obuf++ = SOX_ROUND_CLIP_COUNT(out, effp->clips);
   }
   return SOX_SUCCESS;
@@ -132,12 +135,13 @@
 
 static int kill(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i;
-  for (i = 0; i < p.num_out_channels; ++i) {
-    free(p.out_specs[i].str);
-    free(p.out_specs[i].in_specs);
+  for (i = 0; i < p->num_out_channels; ++i) {
+    free(p->out_specs[i].str);
+    free(p->out_specs[i].in_specs);
   }
-  free(p.out_specs);
+  free(p->out_specs);
   return SOX_SUCCESS;
 }
 
--- a/src/repeat.c
+++ b/src/repeat.c
@@ -28,10 +28,10 @@
   sox_size_t remaining;
   int repeats;
 } priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int getopts(sox_effect_t * effp, int argc, char **argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   do {NUMERIC_PARAMETER(repeats, 0, 1e6)} while (0);
   return argc? lsx_usage(effp) : SOX_SUCCESS;
 }
@@ -38,6 +38,7 @@
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (p->repeats == 0)
     return SOX_EFF_NULL;
 
@@ -52,6 +53,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
     sox_fail("error writing temporary file: %s", strerror(errno));
     return SOX_EOF;
@@ -62,6 +64,7 @@
 
 static int drain(sox_effect_t * effp, sox_sample_t * obuf, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   size_t read = 0;
   sox_sample_t *buf;
   sox_size_t samp;
@@ -153,6 +156,7 @@
 
 static int stop(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   fclose(p->tmp_file);
   return SOX_SUCCESS;
 }
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -169,10 +169,10 @@
     float * dry, * wet[2];
   } chan[2];
 } priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int getopts(sox_effect_t * effp, int argc, char **argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   p->reverberance = p->hf_damping = 50; /* Set non-zero defaults */
   p->stereo_depth = p->room_scale = 100;
 
@@ -192,6 +192,7 @@
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   size_t i;
 
   p->ichannels = p->ochannels = 1;
@@ -216,6 +217,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
                 sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t c, i, w, len = min(*isamp / p->ichannels, *osamp / p->ochannels);
 
   *isamp = len * p->ichannels, *osamp = len * p->ochannels;
@@ -239,6 +241,7 @@
 
 static int stop(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   size_t i;
   for (i = 0; i < p->ichannels; ++i)
     reverb_delete(&p->chan[i].reverb);
--- a/src/reverse.c
+++ b/src/reverse.c
@@ -17,10 +17,10 @@
   off_t         pos;
   FILE          * tmp_file;
 } priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   p->pos = 0;
   p->tmp_file = tmpfile();
   if (p->tmp_file == NULL) {
@@ -33,6 +33,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (fwrite(ibuf, sizeof(*ibuf), *isamp, p->tmp_file) != *isamp) {
     sox_fail("error writing temporary file: %s", strerror(errno));
     return SOX_EOF;
@@ -43,6 +44,7 @@
 
 static int drain(sox_effect_t * effp, sox_sample_t *obuf, sox_size_t *osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   size_t i, j;
 
   if (p->pos == 0) {
@@ -70,6 +72,7 @@
 
 static int stop(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   fclose(p->tmp_file); /* auto-deleted by tmpfile */
   return SOX_SUCCESS;
 }
--- /dev/null
+++ b/src/sd2.c
@@ -1,0 +1,34 @@
+/* libSoX file format: SD2   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(sd2)
+{
+  static char const * const names[] = {"sd2", NULL};
+  static unsigned const write_encodings[] = {SOX_ENCODING_SIGN2, 24, 16, 8,0,0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Sound Designer II";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- a/src/sndfile.c
+++ b/src/sndfile.c
@@ -48,7 +48,6 @@
 static void drain_log_buffer(sox_format_t * ft)
 {
   priv_t * sf = (priv_t *)ft->priv;
-
   sf_command(sf->sf_file, SFC_GET_LOG_INFO, sf->log_buffer, LOG_MAX);
   while (*sf->log_buffer_ptr) {
     static char const warning_prefix[] = "*** Warning : ";
@@ -68,74 +67,78 @@
   }
 }
 
-/* Get sample encoding and size from libsndfile subtype; return value
-   is encoding if conversion was made, or SOX_ENCODING_UNKNOWN for
-   invalid input. If the libsndfile subtype can't be represented in
-   SoX types, use 16-bit signed. */
-static sox_encoding_t sox_encoding_and_size(unsigned format, unsigned * size)
+/* Make libsndfile subtype from sample encoding and size */
+static int ft_enc(unsigned size, sox_encoding_t e)
 {
-  *size = 0;                   /* Default */
-  format &= SF_FORMAT_SUBMASK;
+  if (e == SOX_ENCODING_ULAW      && size ==  8) return SF_FORMAT_ULAW;
+  if (e == SOX_ENCODING_ALAW      && size ==  8) return SF_FORMAT_ALAW;
+  if (e == SOX_ENCODING_SIGN2     && size ==  8) return SF_FORMAT_PCM_S8;
+  if (e == SOX_ENCODING_SIGN2     && size == 16) return SF_FORMAT_PCM_16;
+  if (e == SOX_ENCODING_SIGN2     && size == 24) return SF_FORMAT_PCM_24;
+  if (e == SOX_ENCODING_SIGN2     && size == 32) return SF_FORMAT_PCM_32;
+  if (e == SOX_ENCODING_UNSIGNED  && size ==  8) return SF_FORMAT_PCM_U8;
+  if (e == SOX_ENCODING_FLOAT     && size == 32) return SF_FORMAT_FLOAT;
+  if (e == SOX_ENCODING_FLOAT     && size == 64) return SF_FORMAT_DOUBLE;
+  if (e == SOX_ENCODING_G721      && size ==  4) return SF_FORMAT_G721_32;
+  if (e == SOX_ENCODING_G723      && size ==  3) return SF_FORMAT_G723_24;
+  if (e == SOX_ENCODING_G723      && size ==  5) return SF_FORMAT_G723_40;
+  if (e == SOX_ENCODING_MS_ADPCM  && size ==  4) return SF_FORMAT_MS_ADPCM;
+  if (e == SOX_ENCODING_IMA_ADPCM && size ==  4) return SF_FORMAT_IMA_ADPCM;
+  if (e == SOX_ENCODING_OKI_ADPCM && size ==  4) return SF_FORMAT_VOX_ADPCM;
+  if (e == SOX_ENCODING_DPCM      && size ==  8) return SF_FORMAT_DPCM_8;
+  if (e == SOX_ENCODING_DPCM      && size == 16) return SF_FORMAT_DPCM_16;
+  if (e == SOX_ENCODING_DWVW      && size == 12) return SF_FORMAT_DWVW_12;
+  if (e == SOX_ENCODING_DWVW      && size == 16) return SF_FORMAT_DWVW_16;
+  if (e == SOX_ENCODING_DWVW      && size == 24) return SF_FORMAT_DWVW_24;
+  if (e == SOX_ENCODING_DWVWN     && size ==  0) return SF_FORMAT_DWVW_N;
+  if (e == SOX_ENCODING_GSM       && size ==  0) return SF_FORMAT_GSM610;
+#ifdef HAVE_SNDFILE_1_0_12
+  if (e == SOX_ENCODING_FLAC      && size ==  8) return SF_FORMAT_PCM_S8;
+  if (e == SOX_ENCODING_FLAC      && size == 16) return SF_FORMAT_PCM_16;
+  if (e == SOX_ENCODING_FLAC      && size == 24) return SF_FORMAT_PCM_24;
+  if (e == SOX_ENCODING_FLAC      && size == 32) return SF_FORMAT_PCM_32;
+#endif
+  return 0; /* Bad encoding */
+}
 
-  switch (format) {
-  case SF_FORMAT_PCM_S8:
-    *size = 8;
-    return SOX_ENCODING_SIGN2;
-  case SF_FORMAT_PCM_16:
-    *size = 16;
-    return SOX_ENCODING_SIGN2;
-  case SF_FORMAT_PCM_24:
-    *size = 24;
-    return SOX_ENCODING_SIGN2;
-  case SF_FORMAT_PCM_32:
-    *size = 32;
-    return SOX_ENCODING_SIGN2;
-  case SF_FORMAT_PCM_U8:
-    *size = 8;
-    return SOX_ENCODING_UNSIGNED;
-  case SF_FORMAT_FLOAT:
-    *size = 32;
-    return SOX_ENCODING_FLOAT;
-  case SF_FORMAT_DOUBLE:
-    *size = 64;
-    return SOX_ENCODING_FLOAT;
-  case SF_FORMAT_ULAW:
-    *size = 8;
-    return SOX_ENCODING_ULAW;
-  case SF_FORMAT_ALAW:
-    *size = 8;
-    return SOX_ENCODING_ALAW;
-  case SF_FORMAT_IMA_ADPCM:
-    *size = 16;
-    return SOX_ENCODING_IMA_ADPCM;
-  case SF_FORMAT_MS_ADPCM:
-    *size = 16;
-    return SOX_ENCODING_MS_ADPCM;
-  case SF_FORMAT_GSM610:
-    *size = 16;
-    return SOX_ENCODING_GSM;
-  case SF_FORMAT_VOX_ADPCM:
-    *size = 16;
-    return SOX_ENCODING_OKI_ADPCM;
+/* Convert format's encoding type to libSoX encoding type & size. */
+static sox_encoding_t sox_enc(int ft_encoding, unsigned * size)
+{
+  int sub = ft_encoding & SF_FORMAT_SUBMASK;
+  int type = ft_encoding & SF_FORMAT_TYPEMASK;
 
-  /* For encodings we can't represent, have a sensible default */
-  case SF_FORMAT_G721_32:
-  case SF_FORMAT_G723_24:
-  case SF_FORMAT_G723_40:
-  case SF_FORMAT_DWVW_12:
-  case SF_FORMAT_DWVW_16:
-  case SF_FORMAT_DWVW_24:
-  case SF_FORMAT_DWVW_N:
-  case SF_FORMAT_DPCM_8:
-  case SF_FORMAT_DPCM_16:
-    return SOX_ENCODING_SIGN2;
-
-  default: /* Invalid libsndfile subtype */
-    return SOX_ENCODING_UNKNOWN;
+#ifdef HAVE_SNDFILE_1_0_12
+  if (type == SF_FORMAT_FLAC) switch (sub) {
+    case SF_FORMAT_PCM_S8   : *size =  8; return SOX_ENCODING_FLAC;
+    case SF_FORMAT_PCM_16   : *size = 16; return SOX_ENCODING_FLAC;
+    case SF_FORMAT_PCM_24   : *size = 24; return SOX_ENCODING_FLAC;
   }
-
-  assert(0); /* Should never reach here */
-  return SOX_ENCODING_UNKNOWN;
+#endif
+  switch (sub) {
+    case SF_FORMAT_ULAW     : *size =  8; return SOX_ENCODING_ULAW;
+    case SF_FORMAT_ALAW     : *size =  8; return SOX_ENCODING_ALAW;
+    case SF_FORMAT_PCM_S8   : *size =  8; return SOX_ENCODING_SIGN2;
+    case SF_FORMAT_PCM_16   : *size = 16; return SOX_ENCODING_SIGN2;
+    case SF_FORMAT_PCM_24   : *size = 24; return SOX_ENCODING_SIGN2;
+    case SF_FORMAT_PCM_32   : *size = 32; return SOX_ENCODING_SIGN2;
+    case SF_FORMAT_PCM_U8   : *size =  8; return SOX_ENCODING_UNSIGNED;
+    case SF_FORMAT_FLOAT    : *size = 32; return SOX_ENCODING_FLOAT;
+    case SF_FORMAT_DOUBLE   : *size = 64; return SOX_ENCODING_FLOAT;
+    case SF_FORMAT_G721_32  : *size =  4; return SOX_ENCODING_G721;
+    case SF_FORMAT_G723_24  : *size =  3; return SOX_ENCODING_G723;
+    case SF_FORMAT_G723_40  : *size =  5; return SOX_ENCODING_G723;
+    case SF_FORMAT_MS_ADPCM : *size =  4; return SOX_ENCODING_MS_ADPCM;
+    case SF_FORMAT_IMA_ADPCM: *size =  4; return SOX_ENCODING_IMA_ADPCM;
+    case SF_FORMAT_VOX_ADPCM: *size =  4; return SOX_ENCODING_OKI_ADPCM;
+    case SF_FORMAT_DPCM_8   : *size =  8; return SOX_ENCODING_DPCM;
+    case SF_FORMAT_DPCM_16  : *size = 16; return SOX_ENCODING_DPCM;
+    case SF_FORMAT_DWVW_12  : *size = 12; return SOX_ENCODING_DWVW;
+    case SF_FORMAT_DWVW_16  : *size = 16; return SOX_ENCODING_DWVW;
+    case SF_FORMAT_DWVW_24  : *size = 24; return SOX_ENCODING_DWVW;
+    case SF_FORMAT_DWVW_N   : *size =  0; return SOX_ENCODING_DWVWN;
+    case SF_FORMAT_GSM610   : *size =  0; return SOX_ENCODING_GSM;
+    default                 : *size =  0; return SOX_ENCODING_UNKNOWN;
+  }
 }
 
 static struct {
@@ -202,58 +205,10 @@
   return 0;
 }
 
-/* Make libsndfile subtype from sample encoding and size */
-static int sndfile_format(sox_encoding_t encoding, unsigned size)
-{
-  size = (size + 7) & ~7u;
-  switch (encoding) {
-    case SOX_ENCODING_ULAW:
-      return SF_FORMAT_ULAW;
-    case SOX_ENCODING_ALAW:
-      return SF_FORMAT_ALAW;
-    case SOX_ENCODING_MS_ADPCM:
-      return SF_FORMAT_MS_ADPCM;
-    case SOX_ENCODING_IMA_ADPCM:
-      return SF_FORMAT_IMA_ADPCM;
-    case SOX_ENCODING_OKI_ADPCM:
-      return SF_FORMAT_VOX_ADPCM;
-    case SOX_ENCODING_UNSIGNED:
-      if (size == 8)
-        return SF_FORMAT_PCM_U8;
-      else
-        return 0;
-    case SOX_ENCODING_SIGN2:
-    case SOX_ENCODING_MP3:
-    case SOX_ENCODING_VORBIS:
-#ifdef HAVE_SNDFILE_1_0_12
-    case SOX_ENCODING_FLAC:
-      switch (size) {
-      case 8:
-        return SF_FORMAT_PCM_S8;
-      case 16:
-        return SF_FORMAT_PCM_16;
-      case 24:
-        return SF_FORMAT_PCM_24;
-      case 32:
-        return SF_FORMAT_PCM_32;
-      default: /* invalid size */
-        return 0;
-      }
-      break;
-#endif
-    case SOX_ENCODING_FLOAT:
-      return SF_FORMAT_FLOAT;
-    case SOX_ENCODING_GSM:
-      return SF_FORMAT_GSM610;
-    default: /* Bad encoding */
-      return 0;
-  }
-}
-
 static void start(sox_format_t * ft)
 {
   priv_t * sf = (priv_t *)ft->priv;
-  int subtype = sndfile_format(ft->encoding.encoding, ft->encoding.bits_per_sample? ft->encoding.bits_per_sample : ft->signal.precision);
+  int subtype = ft_enc(ft->encoding.bits_per_sample? ft->encoding.bits_per_sample : ft->signal.precision, ft->encoding.encoding);
   sf->log_buffer_ptr = sf->log_buffer = lsx_malloc(LOG_MAX);
   sf->sf_info = (SF_INFO *)lsx_calloc(1, sizeof(SF_INFO));
 
@@ -270,6 +225,33 @@
     sf->sf_info->frames = ft->signal.length / ft->signal.channels;
 }
 
+static int check_read_params(sox_format_t * ft, unsigned channels,
+    sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, off_t length)
+{
+  ft->signal.length = length;
+
+  if (channels && ft->signal.channels && ft->signal.channels != channels)
+    sox_warn("`%s': overriding number of channels", ft->filename);
+  else ft->signal.channels = channels;
+
+  if (rate && ft->signal.rate && ft->signal.rate != rate)
+    sox_warn("`%s': overriding sample rate", ft->filename);
+  else ft->signal.rate = rate;
+
+  if (encoding && ft->encoding.encoding && ft->encoding.encoding != encoding)
+    sox_warn("`%s': overriding encoding type", ft->filename);
+  else ft->encoding.encoding = encoding;
+
+  if (bits_per_sample && ft->encoding.bits_per_sample && ft->encoding.bits_per_sample != bits_per_sample)
+    sox_warn("`%s': overriding encoding size", ft->filename);
+  ft->encoding.bits_per_sample = bits_per_sample;
+
+  if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample))
+    return SOX_SUCCESS;
+  lsx_fail_errno(ft, EINVAL, "invalid format for this file type");
+  return SOX_EOF;
+}
+
 /*
  * Open file in sndfile.
  */
@@ -276,12 +258,14 @@
 static int startread(sox_format_t * ft)
 {
   priv_t * sf = (priv_t *)ft->priv;
+  unsigned bits_per_sample;
+  sox_encoding_t encoding;
+  sox_rate_t rate;
 
   start(ft);
 
-  /* We'd like to use sf_open_fd, but auto file typing has already
-     invoked stdio buffering. */
-  sf->sf_file = sf_open(ft->filename, SFM_READ, sf->sf_info);
+  sf->sf_file = sf_open_fd(fileno(ft->fp), SFM_READ, sf->sf_info, 1);
+  ft->fp = NULL; /* Transfer ownership of fp to LSF */
   drain_log_buffer(ft);
 
   if (sf->sf_file == NULL) {
@@ -291,21 +275,24 @@
     return SOX_EOF;
   }
 
-  /* Copy format info */
-  ft->encoding.encoding = sox_encoding_and_size((unsigned)sf->sf_info->format, &ft->encoding.bits_per_sample);
-  ft->signal.channels = sf->sf_info->channels;
-  ft->signal.length = sf->sf_info->frames * sf->sf_info->channels;
+  if (!(encoding = sox_enc(sf->sf_info->format, &bits_per_sample))) {
+    lsx_fail_errno(ft, SOX_EFMT, "unsupported sndfile encoding %#x", sf->sf_info->format);
+    return SOX_EOF;
+  }
 
-  /* FIXME: it would be better if LSF were able to do this */
-  if ((sf->sf_info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW) {
-    if (ft->signal.rate == 0) {
-      sox_warn("'%s': sample rate not specified; trying 8kHz", ft->filename);
-      ft->signal.rate = 8000;
-    }
+  /* Don't believe LSF's rate for raw files */
+  if ((sf->sf_info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW && !ft->signal.rate) {
+    sox_warn("'%s': sample rate not specified; trying 8kHz", ft->filename);
+    rate = 8000;
   }
-  else ft->signal.rate = sf->sf_info->samplerate;
+  else rate = sf->sf_info->samplerate;
 
-  return SOX_SUCCESS;
+#if 0 /* FIXME */
+    sox_append_comments(&ft->oob.comments, buf);
+#endif
+
+  return check_read_params(ft, (unsigned)sf->sf_info->channels, rate,
+      encoding, bits_per_sample, (off_t)(sf->sf_info->frames * sf->sf_info->channels));
 }
 
 /*
@@ -315,7 +302,6 @@
 static sox_size_t read_samples(sox_format_t * ft, sox_sample_t *buf, sox_size_t len)
 {
   priv_t * sf = (priv_t *)ft->priv;
-
   /* FIXME: We assume int == sox_sample_t here */
   return (sox_size_t)sf_read_int(sf->sf_file, (int *)buf, (sf_count_t)len);
 }
@@ -335,7 +321,6 @@
 static int startwrite(sox_format_t * ft)
 {
   priv_t * sf = (priv_t *)ft->priv;
-
   start(ft);
   /* If output format is invalid, try to find a sensible default */
   if (!sf_format_check(sf->sf_info)) {
@@ -362,7 +347,8 @@
       sox_warn("cannot use desired output encoding, choosing default");
   }
 
-  sf->sf_file = sf_open(ft->filename, SFM_WRITE, sf->sf_info);
+  sf->sf_file = sf_open_fd(fileno(ft->fp), SFM_WRITE, sf->sf_info, 1);
+  ft->fp = NULL; /* Transfer ownership of fp to LSF */
   drain_log_buffer(ft);
 
   if (sf->sf_file == NULL) {
@@ -382,7 +368,6 @@
 static sox_size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, sox_size_t len)
 {
   priv_t * sf = (priv_t *)ft->priv;
-
   /* FIXME: We assume int == sox_sample_t here */
   return (sox_size_t)sf_write_int(sf->sf_file, (int *)buf, (sf_count_t)len);
 }
@@ -408,36 +393,24 @@
 
 SOX_FORMAT_HANDLER(sndfile)
 {
-  /* Format file suffixes */
-  /* For now, comment out formats built in to SoX */
   static char const * const names[] = {
-    "sndfile", /* special type to force use of sndfile */
+    "sndfile", /* Special type to force use of sndfile for the following: */
+  /* LSF implementation of formats built in to SoX: */
     /* "aif", */
-    /* "wav", */
     /* "au", */
-#ifdef HAVE_SNDFILE_1_0_12
-    "caf",
-#endif
-    /* "flac", */
-    /* "snd", */
-    /* "svx", */
-    "paf",
-    "fap",
     /* "gsm", */
     /* "nist", */
-    /* "ircam", */
-    /* "sf", */
-    /* "voc", */
-    "w64",
     /* "raw", */
-    "mat4",
-    "mat5",
-    "mat",
-    "pvf",
-    "sds",
-    "sd2",
+    /* "sf", "ircam", */
+    /* "snd", */
+    /* "svx", */
+    /* "voc", */
     /* "vox", */
-    "xi",
+    /* "wav", */
+  /* LSF wrappers of formats already wrapped in SoX: */
+    /* "flac", */
+
+    "sds",  /* ?? */
     NULL
   };
 
@@ -454,7 +427,7 @@
     0};
 
   static sox_format_handler_t const format = {SOX_LIB_VERSION_CODE,
-    "Pseudo format to use libsndfile", names, SOX_FILE_NOSTDIO,
+    "Pseudo format to use libsndfile", names, 0,
     startread, read_samples, stopread,
     startwrite, write_samples, stopwrite,
     seek, write_encodings, NULL, sizeof(priv_t)
--- a/src/sox.c
+++ b/src/sox.c
@@ -157,18 +157,14 @@
   }
 
   if (file_count) {
-    if (ofile->ft) {
-      if (!(ofile->ft->handler.flags & SOX_FILE_NOSTDIO)) {
-        struct stat st;
+    if (ofile->ft) {                  
+      if (!success && ofile->ft->fp) {   /* If we failed part way through */
+        struct stat st;                  /* writing a normal file, remove it. */
         fstat(fileno(ofile->ft->fp), &st);
-
-        /* If we didn't succeed and we created an output file, remove it. */
-        if (!success && (st.st_mode & S_IFMT) == S_IFREG)
+        if ((st.st_mode & S_IFMT) == S_IFREG)
           unlink(ofile->ft->filename);
       }
-
-      /* Assumption: we can unlink a file before sox_closing it. */
-      sox_close(ofile->ft);
+      sox_close(ofile->ft); /* Assume we can unlink a file before closing it. */
     }
     free(ofile);
   }
@@ -202,7 +198,7 @@
     fprintf(output, "\n\n");
   }
 
-  fprintf(output, "  Encoding: %-14s", sox_encodings_short_str[ft->encoding.encoding]);
+  fprintf(output, "  Encoding: %-14s", sox_encodings_info[ft->encoding.encoding].name);
   text = sox_find_comment(f->ft->oob.comments, "Comment");
   if (!text)
     text = sox_find_comment(f->ft->oob.comments, "Description");
@@ -286,7 +282,7 @@
       sprintf(buffer, "%u-bit ", ft->encoding.bits_per_sample);
 
     fprintf(output, "Sample Encoding: %s%s\n", buffer,
-        sox_encodings_str[ft->encoding.encoding]);
+        sox_encodings_info[ft->encoding.encoding].desc);
   }
 
   if (full) {
@@ -1115,7 +1111,7 @@
             printf("  ");
             if (s)
               printf("%2u-bit ", s);
-            printf("%s (%u-bit precision)\n", sox_encodings_str[e], sox_precision(e, s));
+            printf("%s (%u-bit precision)\n", sox_encodings_info[e].desc, sox_precision(e, s));
           }
         } while (s);
       }
@@ -1569,7 +1565,7 @@
     case samples: printf("%u\n", ws); break;
     case duration: printf("%s\n", str_time((double)ws / max(ft->signal.rate, 1))); break;
     case bits: printf("%u\n", ft->encoding.bits_per_sample); break;
-    case encoding: printf("%s\n", sox_encodings_str[ft->encoding.encoding]); break;
+    case encoding: printf("%s\n", sox_encodings_info[ft->encoding.encoding].desc); break;
     case annotation: if (ft->oob.comments) {
       sox_comments_t p = ft->oob.comments;
       do printf("%s\n", *p); while (*++p);
--- a/src/sox.h
+++ b/src/sox.h
@@ -210,11 +210,8 @@
   SOX_ENCODING_HCOM      , /*  */
   SOX_ENCODING_WAVPACK   , /*  */
   SOX_ENCODING_WAVPACKF  , /*  */
-
-  SOX_ENCODING_LOSSLESS  , /* Lossless above, lossy below */
-
   SOX_ENCODING_ULAW      , /* u-law signed logs: US telephony, SPARC */
-  SOX_ENCODING_ALAW      , /* A-law signed logs: non-US telephony */
+  SOX_ENCODING_ALAW      , /* A-law signed logs: non-US telephony, Psion */
   SOX_ENCODING_G721      , /* G.721 4-bit ADPCM */
   SOX_ENCODING_G723      , /* G.723 3 or 5 bit ADPCM */
   SOX_ENCODING_CL_ADPCM  , /* Creative Labs 8 --> 2,3,4 bit Compressed PCM */
@@ -222,6 +219,9 @@
   SOX_ENCODING_MS_ADPCM  , /* Microsoft Compressed PCM */
   SOX_ENCODING_IMA_ADPCM , /* IMA Compressed PCM */
   SOX_ENCODING_OKI_ADPCM , /* Dialogic/OKI Compressed PCM */
+  SOX_ENCODING_DPCM      , /*  */
+  SOX_ENCODING_DWVW      , /*  */
+  SOX_ENCODING_DWVWN     , /*  */
   SOX_ENCODING_GSM       , /* GSM 6.10 33byte frame lossy compression */
   SOX_ENCODING_MP3       , /* MP3 compression */
   SOX_ENCODING_VORBIS    , /* Vorbis compression */
@@ -229,11 +229,20 @@
   SOX_ENCODING_AMR_NB    , /* AMR-NB compression */
   SOX_ENCODING_CVSD      , /*  */
   SOX_ENCODING_LPC10     , /*  */
+
   SOX_ENCODINGS            /* End of list marker */
 } sox_encoding_t;
 
-extern const char * const sox_encodings_str[];
-extern const char * const sox_encodings_short_str[];
+typedef struct {
+  unsigned flags;
+  #define SOX_LOSSY1 1     /* encode, decode, encode, decode: lossy once */
+  #define SOX_LOSSY2 2     /* encode, decode, encode, decode: lossy twice */
+
+  char const * name;
+  char const * desc;
+} sox_encodings_info_t;
+
+extern sox_encodings_info_t const sox_encodings_info[];
 
 typedef enum {SOX_OPTION_NO, SOX_OPTION_YES, SOX_OPTION_DEFAULT} sox_option_t;
 
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -158,6 +158,8 @@
 #define lsx_rawstopread NULL
 #define lsx_rawstopwrite NULL
 
+extern sox_format_handler_t const * sox_sndfile_format_fn(void);
+
 
 
 /*--------------------------------- Effects ----------------------------------*/
--- a/src/splice.c
+++ b/src/splice.c
@@ -83,44 +83,44 @@
   float * buffer;
   unsigned state;
 } priv_t;
-#define p (*(priv_t *)effp->priv)
 
 static int parse(sox_effect_t * effp, char * * argv, sox_rate_t rate)
 {
+  priv_t * p = (priv_t *)effp->priv;
   char const * next;
   sox_size_t i, buffer_size;
 
-  p.max_buffer_size = 0;
-  for (i = 0; i < p.nsplices; ++i) {
+  p->max_buffer_size = 0;
+  for (i = 0; i < p->nsplices; ++i) {
     if (argv) /* 1st parse only */
-      p.splices[i].str = lsx_strdup(argv[i]);
+      p->splices[i].str = lsx_strdup(argv[i]);
 
-    p.splices[i].overlap = p.splices[i].search = rate * 0.01 + .5;
+    p->splices[i].overlap = p->splices[i].search = rate * 0.01 + .5;
 
-    next = lsx_parsesamples(rate, p.splices[i].str, &p.splices[i].start, 't');
+    next = lsx_parsesamples(rate, p->splices[i].str, &p->splices[i].start, 't');
     if (next == NULL) break;
 
     if (*next == ',') {
-      next = lsx_parsesamples(rate, next + 1, &p.splices[i].overlap, 't');
+      next = lsx_parsesamples(rate, next + 1, &p->splices[i].overlap, 't');
       if (next == NULL) break;
-      p.splices[i].overlap *= 2;
+      p->splices[i].overlap *= 2;
       if (*next == ',') {
-        next = lsx_parsesamples(rate, next + 1, &p.splices[i].search, 't');
+        next = lsx_parsesamples(rate, next + 1, &p->splices[i].search, 't');
         if (next == NULL) break;
-        p.splices[i].search *= 2;
+        p->splices[i].search *= 2;
       }
     }
     if (*next != '\0') break;
-    p.splices[i].overlap = max(p.splices[i].overlap + 4, 16);
-    p.splices[i].overlap &= ~7; /* Make divisible by 8 for loop optimisation */
+    p->splices[i].overlap = max(p->splices[i].overlap + 4, 16);
+    p->splices[i].overlap &= ~7; /* Make divisible by 8 for loop optimisation */
 
-    if (i > 0 && p.splices[i].start <= p.splices[i-1].start) break;
-    if (p.splices[i].start < p.splices[i].overlap) break;
-    p.splices[i].start -= p.splices[i].overlap;
-    buffer_size = 2 * p.splices[i].overlap + p.splices[i].search;
-    p.max_buffer_size = max(p.max_buffer_size, buffer_size);
+    if (i > 0 && p->splices[i].start <= p->splices[i-1].start) break;
+    if (p->splices[i].start < p->splices[i].overlap) break;
+    p->splices[i].start -= p->splices[i].overlap;
+    buffer_size = 2 * p->splices[i].overlap + p->splices[i].search;
+    p->max_buffer_size = max(p->max_buffer_size, buffer_size);
   }
-  if (i < p.nsplices)
+  if (i < p->nsplices)
     return lsx_usage(effp);
   return SOX_SUCCESS;
 }
@@ -127,20 +127,22 @@
 
 static int create(sox_effect_t * effp, int n, char * * argv)
 {
-  p.splices = lsx_calloc(p.nsplices = n, sizeof(*p.splices));
+  priv_t * p = (priv_t *)effp->priv;
+  p->splices = lsx_calloc(p->nsplices = n, sizeof(*p->splices));
   return parse(effp, argv, 96000.); /* No rate yet; parse with dummy */
 }
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i;
 
   parse(effp, 0, effp->in_signal.rate); /* Re-parse now rate is known */
-  p.buffer = lsx_calloc(p.max_buffer_size * effp->in_signal.channels, sizeof(*p.buffer));
-  p.in_pos = p.buffer_pos = p.splices_pos = 0;
-  p.state = p.splices_pos != p.nsplices && p.in_pos == p.splices[p.splices_pos].start;
-  for (i = 0; i < p.nsplices; ++i)
-    if (p.splices[i].overlap)
+  p->buffer = lsx_calloc(p->max_buffer_size * effp->in_signal.channels, sizeof(*p->buffer));
+  p->in_pos = p->buffer_pos = p->splices_pos = 0;
+  p->state = p->splices_pos != p->nsplices && p->in_pos == p->splices[p->splices_pos].start;
+  for (i = 0; i < p->nsplices; ++i)
+    if (p->splices[i].overlap)
       return SOX_SUCCESS;
   return SOX_EFF_NULL;
 }
@@ -148,6 +150,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
     sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t c, idone = 0, odone = 0;
   *isamp /= effp->in_signal.channels;
   *osamp /= effp->in_signal.channels;
@@ -154,10 +157,10 @@
 
   while (sox_true) {
 copying:
-    if (p.state == 0) {
-      for (; idone < *isamp && odone < *osamp; ++idone, ++odone, ++p.in_pos) {
-        if (p.splices_pos != p.nsplices && p.in_pos == p.splices[p.splices_pos].start) {
-          p.state = 1;
+    if (p->state == 0) {
+      for (; idone < *isamp && odone < *osamp; ++idone, ++odone, ++p->in_pos) {
+        if (p->splices_pos != p->nsplices && p->in_pos == p->splices[p->splices_pos].start) {
+          p->state = 1;
           goto buffering;
         }
         for (c = 0; c < effp->in_signal.channels; ++c)
@@ -167,36 +170,36 @@
     }
 
 buffering:
-    if (p.state == 1) {
-      sox_size_t buffer_size = (2 * p.splices[p.splices_pos].overlap + p.splices[p.splices_pos].search) * effp->in_signal.channels;
-      for (; idone < *isamp; ++idone, ++p.in_pos) {
-        if (p.buffer_pos == buffer_size) {
-          p.buffer_pos = do_splice(p.buffer,
-              p.splices[p.splices_pos].overlap,
-              p.splices[p.splices_pos].search,
+    if (p->state == 1) {
+      sox_size_t buffer_size = (2 * p->splices[p->splices_pos].overlap + p->splices[p->splices_pos].search) * effp->in_signal.channels;
+      for (; idone < *isamp; ++idone, ++p->in_pos) {
+        if (p->buffer_pos == buffer_size) {
+          p->buffer_pos = do_splice(p->buffer,
+              p->splices[p->splices_pos].overlap,
+              p->splices[p->splices_pos].search,
               effp->in_signal.channels) * effp->in_signal.channels;
-          p.state = 2;
+          p->state = 2;
           goto flushing;
           break;
         }
         for (c = 0; c < effp->in_signal.channels; ++c)
-          p.buffer[p.buffer_pos++] = SOX_SAMPLE_TO_FLOAT_32BIT(*ibuf++, effp->clips);
+          p->buffer[p->buffer_pos++] = SOX_SAMPLE_TO_FLOAT_32BIT(*ibuf++, effp->clips);
       }
       break;
     }
 
 flushing:
-    if (p.state == 2) {
-      sox_size_t buffer_size = (2 * p.splices[p.splices_pos].overlap + p.splices[p.splices_pos].search) * effp->in_signal.channels;
+    if (p->state == 2) {
+      sox_size_t buffer_size = (2 * p->splices[p->splices_pos].overlap + p->splices[p->splices_pos].search) * effp->in_signal.channels;
       for (; odone < *osamp; ++odone) {
-        if (p.buffer_pos == buffer_size) {
-          p.buffer_pos = 0;
-          ++p.splices_pos;
-          p.state = p.splices_pos != p.nsplices && p.in_pos == p.splices[p.splices_pos].start;
+        if (p->buffer_pos == buffer_size) {
+          p->buffer_pos = 0;
+          ++p->splices_pos;
+          p->state = p->splices_pos != p->nsplices && p->in_pos == p->splices[p->splices_pos].start;
           goto copying;
         }
         for (c = 0; c < effp->in_signal.channels; ++c)
-          *obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(p.buffer[p.buffer_pos++], effp->clips);
+          *obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(p->buffer[p->buffer_pos++], effp->clips);
       }
       break;
     }
@@ -215,18 +218,20 @@
 
 static int stop(sox_effect_t * effp)
 {
-  if (p.splices_pos != p.nsplices)
-    sox_warn("Input audio too short; splices not made: %u", p.nsplices - p.splices_pos);
-  free(p.buffer);
+  priv_t * p = (priv_t *)effp->priv;
+  if (p->splices_pos != p->nsplices)
+    sox_warn("Input audio too short; splices not made: %u", p->nsplices - p->splices_pos);
+  free(p->buffer);
   return SOX_SUCCESS;
 }
 
 static int kill(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   unsigned i;
-  for (i = 0; i < p.nsplices; ++i)
-    free(p.splices[i].str);
-  free(p.splices);
+  for (i = 0; i < p->nsplices; ++i)
+    free(p->splices[i].str);
+  free(p->splices);
   return SOX_SUCCESS;
 }
 
--- a/src/tempo.c
+++ b/src/tempo.c
@@ -203,10 +203,10 @@
   sox_bool    quick_search;
   double      factor, segment_ms, search_ms, overlap_ms;
 } priv_t;
-#define p ((priv_t *)effp->priv)
 
 static int getopts(sox_effect_t * effp, int argc, char **argv)
 {
+  priv_t * p = (priv_t *)effp->priv;
   p->segment_ms = 82; /* Set non-zero defaults: */
   p->search_ms  = 14;
   p->overlap_ms = 12;
@@ -225,6 +225,7 @@
 
 static int start(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   if (p->factor == 1)
     return SOX_EFF_NULL;
 
@@ -237,6 +238,7 @@
 static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
                 sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   sox_size_t i;
   /* odone must be size_t 'cos tempo_output arg. is. (!= sox_size_t on amd64) */
   size_t odone = *osamp /= effp->in_signal.channels;
@@ -259,6 +261,7 @@
 
 static int drain(sox_effect_t * effp, sox_sample_t * obuf, sox_size_t * osamp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   static sox_size_t isamp = 0;
   tempo_flush(p->tempo);
   return flow(effp, 0, obuf, &isamp, osamp);
@@ -266,6 +269,7 @@
 
 static int stop(sox_effect_t * effp)
 {
+  priv_t * p = (priv_t *)effp->priv;
   tempo_delete(p->tempo);
   return SOX_SUCCESS;
 }
--- a/src/tests.sh
+++ b/src/tests.sh
@@ -131,12 +131,13 @@
 
   format1=u3
   convertToAndFrom s3 u3 s4 u4 raw Raw wav aiff aifc flac sph wv
+  (samples=23500; convertToAndFrom paf) || exit 1
 
   format1=s4
-  convertToAndFrom s4 u4 Raw wav aiff aifc caf sph wv
+  convertToAndFrom s4 u4 Raw wav aiff aifc caf sph wv mat4 mat5
 
   format1=al
-  convertToAndFrom al s2 u2 s4 raw Raw dat aiff aifc flac caf
+  convertToAndFrom al s2 u2 s4 raw Raw dat aiff aifc flac caf w64
 
   format1=ul
   convertToAndFrom ul s2 u2 s4 raw Raw dat aiff aifc flac caf sph
@@ -190,15 +191,20 @@
   done
 }
 
+# Don't try to test un-built formats
+skip_check () {
+  while [ $# -ne 0 ]; do
+    ${bindir}/sox --help|grep "^AUDIO FILE.*\<$1\>">/dev/null || skip="$1 $skip"
+    shift
+  done
+}
 
+
 # Run tests
 
 ${builddir}/sox_sample_test || exit 1
 
-# Don't try to test unsupported stuff
-${bindir}/sox --help|grep "^AUDIO FILE.*\<wv\>">/dev/null || skip="wv $skip"
-${bindir}/sox --help|grep "^AUDIO FILE.*\<flac\>">/dev/null || skip="flac $skip"
-${bindir}/sox --help|grep "^AUDIO FILE.*\<caf\>" >/dev/null || skip="caf $skip"
+skip_check caf flac mat4 mat5 paf w64 wv
 
 vectors=0
 
--- /dev/null
+++ b/src/w64.c
@@ -1,0 +1,43 @@
+/* libSoX file format: W64   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(w64)
+{
+  static char const * const names[] = {"w64", NULL};
+  static unsigned const write_encodings[] = {
+    SOX_ENCODING_SIGN2, 16, 24, 32, 0,
+    SOX_ENCODING_UNSIGNED, 8, 0,
+    SOX_ENCODING_FLOAT, 32, 64, 0,
+    SOX_ENCODING_ALAW, 8, 0,
+    SOX_ENCODING_ULAW, 8, 0,
+    SOX_ENCODING_IMA_ADPCM, 4, 0,
+    SOX_ENCODING_MS_ADPCM, 4, 0,
+    SOX_ENCODING_GSM, 0,
+    0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Sound Forge Audio Format";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif
--- a/src/wav.h
+++ /dev/null
@@ -1,47 +1,0 @@
-/*
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-/* wav.h - various structures and defines used by WAV converter. */
-
-#ifndef WAV_H_INCLUDED
-#define WAV_H_INCLUDED
-
-/* purloined from public Microsoft RIFF docs */
-
-#define	WAVE_FORMAT_UNKNOWN		(0x0000U)
-#define	WAVE_FORMAT_PCM			(0x0001U) 
-#define	WAVE_FORMAT_ADPCM		(0x0002U)
-#define WAVE_FORMAT_IEEE_FLOAT          (0x0003U)
-#define	WAVE_FORMAT_ALAW		(0x0006U)
-#define	WAVE_FORMAT_MULAW		(0x0007U)
-#define	WAVE_FORMAT_OKI_ADPCM		(0x0010U)
-#define WAVE_FORMAT_IMA_ADPCM		(0x0011U)
-#define	WAVE_FORMAT_DIGISTD		(0x0015U)
-#define	WAVE_FORMAT_DIGIFIX		(0x0016U)
-#define WAVE_FORMAT_DOLBY_AC2           (0x0030U)
-#define WAVE_FORMAT_GSM610              (0x0031U)
-#define WAVE_FORMAT_ROCKWELL_ADPCM      (0x003bU)
-#define WAVE_FORMAT_ROCKWELL_DIGITALK   (0x003cU)
-#define WAVE_FORMAT_G721_ADPCM          (0x0040U)
-#define WAVE_FORMAT_G728_CELP           (0x0041U)
-#define WAVE_FORMAT_MPEG                (0x0050U)
-#define WAVE_FORMAT_MPEGLAYER3          (0x0055U)
-#define WAVE_FORMAT_G726_ADPCM          (0x0064U)
-#define WAVE_FORMAT_G722_ADPCM          (0x0065U)
-#define WAVE_FORMAT_EXTENSIBLE          (0xfffeU)
-
-#endif /* WAV_H_INCLUDED */
-
--- /dev/null
+++ b/src/xi.c
@@ -1,0 +1,34 @@
+/* libSoX file format: XI   Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+#if defined HAVE_SNDFILE_H
+
+SOX_FORMAT_HANDLER(xi)
+{
+  static char const * const names[] = {"xi", NULL};
+  static unsigned const write_encodings[] = {SOX_ENCODING_DPCM, 16, 8, 0, 0};
+  static sox_format_handler_t handler;
+  handler = *sox_sndfile_format_fn();
+  handler.description = "Fasttracker 2";
+  handler.names = names;
+  handler.write_formats = write_encodings;
+  return &handler;
+}
+
+#endif