shithub: sox

Download patch

ref: 9b8b4594a712f8490048af99dd3f93480558faab
parent: 49be06378c40d1b08ec62e9451b394d7a05d9def
parent: 383e012470f4f62436dee6c4a5ef2169329a8ab4
author: Doug Cook <idigdoug@users.sourceforge.net>
date: Mon Dec 26 19:04:40 EST 2011

Merge branch 'master' of ssh://sox.git.sourceforge.net/gitroot/sox/sox

--- a/ChangeLog
+++ b/ChangeLog
@@ -13,7 +13,27 @@
   ated in  [F(ormat)] [E(ffect)]   Replacement
   -------  ----------------------  ----------------------
   14.3.0   O --interactive         --no-clobber
+  14.3.0   E filter                ~=sinc
+  14.3.0   E norm -b, norm -i      gain -B, gain -en
+  14.3.0   PLAY_RATE_ARG           SOX_OPTS
+  14.2.0   E key alias             pitch
+  14.2.0   E pan                   ~= mixer/remix
+  14.1.0   E resample alias        rate
+  14.1.0   E polyphase alias       rate
+  14.1.0   E rabbit alias          rate
 
+Previously deprecated features (to be removed in future):
+
+  Deprec-  Feature    [O(ption)]                           Removal
+  ated in  [F(ormat)] [E(ffect)]   Replacement             due after
+  -------  ----------------------  ----------------------  -------
+  14.3.1   F mp3: lame 3.97        lame > 3.97             14.3.2
+  14.3.1   F sndfile: sndfile 1.0.11 sndfile > 1.0.11      14.3.1
+  14.3.0   F flac: libFLAC 1.1.2,3 libFLAC > 1.1.3         14.3.1
+  14.3.0   O -1/-2/-3/-4/-8        -b                      14.4.0
+  14.3.0   O -s/-u/-f              -e                      14.4.0
+  14.3.0   O -A/-U/-o/-i/-a/-g     -e                      14.4.0
+
 File formats:
 
   o Mention in man pages that WAV files support floating point encodings.
@@ -45,7 +65,7 @@
   o Fix crashes in compand and mcompand effects. [3420893] (Ulrich Klauer)
   o Let the delay effect gracefully handle the special case that a delay can
     be more than the input length. [3055399] (Ulrich Klauer)
-  o New hilbert effect. (Ulrich Klauer)
+  o New hilbert and downsample effects. (Ulrich Klauer)
 
 Misc:
 
--- a/msvc10/LibSoX.vcxproj
+++ b/msvc10/LibSoX.vcxproj
@@ -165,7 +165,6 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
     </ClCompile>
-    <ClCompile Include="..\src\hilbert.c" />
     <ClCompile Include="..\src\oss.c">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -207,15 +206,16 @@
     <ClCompile Include="..\src\dft_filter.c" />
     <ClCompile Include="..\src\dither.c" />
     <ClCompile Include="..\src\divide.c" />
+    <ClCompile Include="..\src\downsample.c" />
     <ClCompile Include="..\src\earwax.c" />
     <ClCompile Include="..\src\echo.c" />
     <ClCompile Include="..\src\echos.c" />
     <ClCompile Include="..\src\fade.c" />
-    <ClCompile Include="..\src\filter.c" />
     <ClCompile Include="..\src\fir.c" />
     <ClCompile Include="..\src\firfit.c" />
     <ClCompile Include="..\src\flanger.c" />
     <ClCompile Include="..\src\gain.c" />
+    <ClCompile Include="..\src\hilbert.c" />
     <ClCompile Include="..\src\input.c" />
     <ClCompile Include="..\src\ladspa.c" />
     <ClCompile Include="..\src\loudness.c" />
@@ -226,7 +226,6 @@
     <ClCompile Include="..\src\output.c" />
     <ClCompile Include="..\src\overdrive.c" />
     <ClCompile Include="..\src\pad.c" />
-    <ClCompile Include="..\src\pan.c" />
     <ClCompile Include="..\src\phaser.c" />
     <ClCompile Include="..\src\rate.c" />
     <ClCompile Include="..\src\remix.c" />
@@ -344,4 +343,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
--- a/msvc10/LibSoX.vcxproj.filters
+++ b/msvc10/LibSoX.vcxproj.filters
@@ -231,9 +231,6 @@
     <ClCompile Include="..\src\fade.c">
       <Filter>Effect Sources</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\filter.c">
-      <Filter>Effect Sources</Filter>
-    </ClCompile>
     <ClCompile Include="..\src\fir.c">
       <Filter>Effect Sources</Filter>
     </ClCompile>
@@ -276,9 +273,6 @@
     <ClCompile Include="..\src\pad.c">
       <Filter>Effect Sources</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\pan.c">
-      <Filter>Effect Sources</Filter>
-    </ClCompile>
     <ClCompile Include="..\src\phaser.c">
       <Filter>Effect Sources</Filter>
     </ClCompile>
@@ -612,5 +606,8 @@
     <ClCompile Include="..\src\upsample.c">
       <Filter>Effect Sources</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\downsample.c">
+      <Filter>Effect Sources</Filter>
+    </ClCompile>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
--- a/msvc9/LibSoX.vcproj
+++ b/msvc9/LibSoX.vcproj
@@ -680,6 +680,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\downsample.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\earwax.c"
 				>
 			</File>
@@ -696,10 +700,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\src\filter.c"
-				>
-			</File>
-			<File
 				RelativePath="..\src\fir.c"
 				>
 			</File>
@@ -757,10 +757,6 @@
 			</File>
 			<File
 				RelativePath="..\src\pad.c"
-				>
-			</File>
-			<File
-				RelativePath="..\src\pan.c"
 				>
 			</File>
 			<File
--- a/sox.1
+++ b/sox.1
@@ -131,7 +131,7 @@
 .EE
 records half an hour of stereo audio, and
 .EX
-   play \-q take1.aiff & rec \-M take1.aiff take1-dub.aiff
+   play \-q take1.aiff & rec \-M take1.aiff take1\-dub.aiff
 .EE
 (with POSIX shell and where supported by hardware)
 records a new track in a multi-track recording.  Finally,
@@ -194,7 +194,7 @@
 The term `bit-rate' is a measure of the amount of storage occupied by an
 encoded audio signal over a unit of time.  It can depend on all of the
 above and is typically denoted as a number of kilo-bits per second
-(kbps).  An A-law telephony signal has a bit-rate of 64 kbs. MP3-encoded
+(kbps).  An A-law telephony signal has a bit-rate of 64 kbps. MP3-encoded
 stereo music typically has a bit-rate of 128\-196 kbps. FLAC-encoded
 stereo music typically has a bit-rate of 550\-760 kbps.
 .SP
@@ -342,7 +342,7 @@
 Many file formats that compress audio discard some of the audio signal
 information whilst doing so. Converting to such a format and then converting
 back again will not produce an exact copy of the original audio.  This
-is the case for many formats used in telephony (e.g.  A-law, GSM) where
+is the case for many formats used in telephony (e.g. A-law, GSM) where
 low signal bandwidth is more important than high audio fidelity, and for
 many formats used in portable music players (e.g. MP3, Vorbis) where
 adequate fidelity can be retained even with the large compression ratios
@@ -740,7 +740,7 @@
 SoX's global options.
 For example:
 .EX
-   SOX_OPTS="\-\-buffer 20000 \-\-play-rate-arg \-hs \-\-temp /mnt/temp"
+   SOX_OPTS="\-\-buffer 20000 \-\-play\-rate\-arg \-hs \-\-temp /mnt/temp"
 .EE
 Note that setting SOX_OPTS can potentially create unwanted changes in
 the behaviour of scripts or other programs that invoke SoX.  SOX_OPTS
@@ -812,7 +812,7 @@
 combining methods.
 .TP
 \fB\-D\fR, \fB\-\-no\-dither\fR
-Disable automatic dither\*msee `Dither' above.  An example of why this
+Disable automatic dither\*msee `Dithering' above.  An example of why this
 might occasionally be useful is if a file has been converted from 16 to
 24 bit with the intention of doing some processing on it, but in fact
 no processing is needed after all and the original 16 bit file has
@@ -1228,7 +1228,7 @@
 .TP
 \fB\-s\fR\^/\fB\-u\fR\^/\fB\-f\fR\^/\fB\-A\fR\^/\fB\-U\fR\^/\fB\-o\fR\^/\fB\-i\fR\^/\fB\-a\fR\^/\fB\-g\fR
 Deprecated aliases for specifying the encoding types
-\fBsigned-integer\fR, \fBunsigned-integer\fR, \fBfloating-point\fR, \fBmu-law\fR, \fBa-law\fR, \fBoki-adpcm\fR, \fBima-adpcm\fR, \fBms-adpcm\fR, \fBgsm-full-rate\fR
+\fBsigned-integer\fR, \fBunsigned-integer\fR, \fBfloating-point\fR, \fBa-law\fR, \fBmu-law\fR, \fBoki-adpcm\fR, \fBima-adpcm\fR, \fBms-adpcm\fR, \fBgsm-full-rate\fR
 respectively (see
 .B \-e
 above).
@@ -1882,11 +1882,11 @@
 CD player), or simply play the correctly de-emphasised audio files on the
 PC.  For example:
 .EX
-   sox track1.wav track1-deemph.wav deemph
+   sox track1.wav track1\-deemph.wav deemph
 .EE
 and then burn track1-deemph.wav to CD, or
 .EX
-   play track1-deemph.wav
+   play track1\-deemph.wav
 .EE
 or simply
 .EX
@@ -1923,7 +1923,7 @@
 	delay 0 .05 .1 .15 .2 .25 remix \- fade 0 4 .1 norm \-1
 .EE
 .TP
-\fBdither\fR [\fB\-a\fR] [\fB\-S\fR\^|\^\fB\-s\fR\^|\^\fB\-f \fIfilter\fR]
+\fBdither\fR [\fB\-S\fR\^|\^\fB\-s\fR\^|\^\fB\-f \fIfilter\fR] [\fB\-a\fR] [\fB\-p \fIprecision\fR]
 Apply dithering to the audio.
 Dithering deliberately adds a small amount of noise to the signal in
 order to mask audible quantization effects that can occur if the output
@@ -1964,6 +1964,10 @@
 .BR fade ,
 and concatencate.
 .SP
+The
+.B \-p
+option allows overriding the target precision.
+.SP
 If the SoX global option
 .B \-R
 option is not given, then the pseudo-random number generator used to
@@ -1973,8 +1977,19 @@
 This effect should not be followed by any other effect that
 affects the audio.
 .SP
-See also the `Dither' section above.
+See also the `Dithering' section above.
 .TP
+\fBdownsample [\fIfactor\fR(2)]
+Downsample the signal by an integer factor: Only the first out of
+each \fIfactor\fR samples is retained, the others are discarded.
+.SP
+No decimation filter is applied.  If the input is not a properly
+bandlimited baseband signal, aliasing will occur.  This may be
+desirable, e.g., for frequency translation.
+.SP
+For a general resampling effect with anti-aliasing, see \fBrate\fR.  See
+also \fBupsample\fR.
+.TP
 \fBearwax\fR
 Makes audio easier to listen to on headphones.
 Adds `cues' to 44\*d1kHz stereo (i.e. audio CD format) audio so that
@@ -2125,12 +2140,14 @@
 .EX
    # HP filter
    # freq=10000
-     1.2311233052619888e-01
-    \-4.4777096106211783e-01
-     5.1031563346705155e-01
-    \-6.6502926320995331e-02
+     1.2311233052619888e\-01
+    \-4.4777096106211783e\-01
+     5.1031563346705155e\-01
+    \-6.6502926320995331e\-02
    ...
 .EE
+.SP
+This effect supports the \fB\-\-plot\fR global option.
 .TP
 \fBflanger\fR [\fIdelay depth regen width speed shape phase interp\fR]
 Apply a flanging effect to the audio.
@@ -2328,7 +2345,7 @@
 An odd-tap Hilbert transform filter has a bandpass characteristic,
 attenuating the lowest and highest frequencies.  Its bandwidth can be
 controlled by the number of filter taps, which can be specified with
-\fB-n\fR.  By default, the number of taps is chosen for a cutoff
+\fB\-n\fR.  By default, the number of taps is chosen for a cutoff
 frequency of about 75 Hz.
 .SP
 This effect supports the \fB\-\-plot\fR global option.
@@ -2509,13 +2526,6 @@
 is just an alias for \fBgain \-n\fR; see the
 .B gain
 effect for details.
-.SP
-Note that \fBnorm\fR's
-.B \-i
-and
-.B \-b
-options are deprecated (having been superseded by \fBgain \-en\fR and
-\fBgain \-B\fR respectively) and will be removed in a future release.
 .TP
 \fBoops\fR
 Out Of Phase Stereo effect.
@@ -2656,7 +2666,8 @@
 .I Rej dB
 is the level of noise rejection.  Increasing levels of resampling
 quality come at the expense of increasing amounts of time to process the
-audio.  If no quality option is given, the quality level used is `high'.
+audio.  If no quality option is given, the quality level used is `high'
+(but see `Playing & Recording Audio' above regarding playback).
 .SP
 The `quick' algorithm uses cubic interpolation; all others use
 band-limited interpolation.  By default, all algorithms have
@@ -2709,7 +2720,7 @@
 .TE
 .DT
 .SP
-N.B.  Override options can not be used with the `quick' or `low'
+N.B.  Override options cannot be used with the `quick' or `low'
 quality algorithms.
 .SP
 All resamplers use filters that can sometimes create `echo' (a.k.a.
@@ -2832,7 +2843,7 @@
 copies of channels 6, 7, and 8 in the input file, and channel 4 is silent.
 Whereas
 .EX
-   sox input.wav output.wav remix 1-3,7 3
+   sox input.wav output.wav remix 1\-3,7 3
 .EE
 creates a (somewhat bizarre) stereo output file where the left channel
 is a mix-down of input channels 1, 2, 3, and 7, and the right channel is
@@ -2930,7 +2941,7 @@
 chans=\`soxi \-c "$1"\`
 while [ $chans \-ge 1 ]; do
    chans0=\`printf %02i $chans\`   # 2 digits hence up to 99 chans
-   out=\`echo "$1"|sed "s/\\(.*\\)\\.\\(.*\\)/\\1-$chans0.\\2/"\`
+   out=\`echo "$1"|sed "s/\\(.*\\)\\.\\(.*\\)/\\1\-$chans0.\\2/"\`
    sox "$1" "$out" remix $chans
    chans=\`expr $chans \- 1\`
 done
@@ -3761,11 +3772,11 @@
 For example, the following produces a 3 second, 48kHz,
 audio file containing a sine-wave swept from 300 to 3300\ Hz:
 .EX
-   sox \-n output.wav synth 3 sine 300-3300
+   sox \-n output.wav synth 3 sine 300\-3300
 .EE
 and this produces an 8\ kHz version:
 .EX
-   sox \-r 8000 \-n output.wav synth 3 sine 300-3300
+   sox \-r 8000 \-n output.wav synth 3 sine 300\-3300
 .EE
 Multiple channels can be synthesised by specifying the set of
 parameters shown between braces multiple times;
@@ -3772,13 +3783,13 @@
 the following puts the swept tone in the left channel and adds `brown'
 noise in the right:
 .EX
-   sox \-n output.wav synth 3 sine 300-3300 brownnoise
+   sox \-n output.wav synth 3 sine 300\-3300 brownnoise
 .EE
 The following example shows how two synth effects can be cascaded
 to create a more complex waveform:
 .EX
 .ne 2
-   play \-n synth 0.5 sine 200-500 synth 0.5 sine fmod 700-100
+   play \-n synth 0.5 sine 200\-500 synth 0.5 sine fmod 700\-100
 .EE
 Frequencies can also be given in `scientific' note notation, or, by
 prefixing a `%' character, as a number of semitones relative to
@@ -3785,7 +3796,7 @@
 `middle A' (440\ Hz).  For example, the following could be used to
 help tune a guitar's low `E' string:
 .EX
-   play \-n synth 4 pluck %-29
+   play \-n synth 4 pluck %\-29
 .EE
 or with a (Bourne shell) loop, the whole guitar:
 .EX
@@ -4002,7 +4013,7 @@
 \fBvad \fR[\fIoptions\fR]
 Voice Activity Detector.  Attempts to trim silence and quiet
 background sounds from the ends of (fairly high resolution
-i.e. 16-bit, 44-48kHz) recordings of speech.  The algorithm currently
+i.e. 16-bit, 44\-48kHz) recordings of speech.  The algorithm currently
 uses a simple cepstral power measurement to detect voice, so may be
 fooled by other things, especially music.  The effect can trim only
 from the front of the audio, so in order to trim from the back, the
@@ -4081,10 +4092,10 @@
 `Brick-wall' frequency of low-pass filter applied at the input to the
 detector algorithm.
 .IP \fB\-H\ \fInum\fR
-`Brick-wall' quefrency of high-pass lifter used in the detector
+`Brick-wall' frequency of high-pass lifter used in the detector
 algorithm.
 .IP \fB\-L\ \fInum\fR
-`Brick-wall' quefrency of low-pass lifter used in the detector
+`Brick-wall' frequency of low-pass lifter used in the detector
 algorithm.
 .RE
 .TP
@@ -4159,75 +4170,6 @@
 for a volume-changing effect with different capabilities, and
 .B compand
 for a dynamic-range compression/expansion/limiting effect.
-.SS Deprecated Effects
-The following effects have been renamed or have their functionality
-included in another effect; they continue to work in this version of
-SoX but may be removed in future.
-.TP
-\fBfilter\fR [\fIlow\fR]\fB\-\fR[\fIhigh\fR] [\fIwindow-len\fR [\fIbeta\fR]]
-Apply a sinc-windowed lowpass, highpass, or bandpass filter of given
-window length to the signal.
-This effect has been superseded by the \fBsinc\fR effect.
-Compared with `sinc', `filter' is slower and has fewer capabilities.
-.SP
-\fIlow\fR refers to the frequency of the lower 6dB corner of the filter.
-\fIhigh\fR refers to the frequency of the upper 6dB corner of the filter.
-.SP
-A low-pass filter is obtained by leaving \fIlow\fR unspecified, or 0.
-A high-pass filter is obtained by leaving \fIhigh\fR unspecified, or 0,
-or greater than or equal to the Nyquist frequency.
-.SP
-The \fIwindow-len\fR, if unspecified, defaults to 128.
-Longer windows give a sharper cut-off, smaller windows a more gradual cut-off.
-.SP
-The \fIbeta\fR parameter
-determines the type of filter window used.  Any value greater than 2 is
-the beta for a Kaiser window.  Beta \(<= 2 selects a Blackman-Nuttall window.
-If unspecified, the default is a Kaiser window with beta 16.
-.SP
-In the case of Kaiser window (beta > 2), lower betas produce a
-somewhat faster transition from pass-band to stop-band, at the cost of
-noticeable artifacts. A beta of 16 is the default, beta less than 10
-is not recommended. If you want a sharper cut-off, don't use low
-beta's, use a longer sample window. A Blackman-Nuttall window is selected by
-specifying any `beta' \(<= 2, and the Blackman-Nuttall window has somewhat
-steeper cut-off than the default Kaiser window. You will probably not
-need to use the beta parameter at all, unless you are just curious
-about comparing the effects of Blackman-Nuttall vs. Kaiser windows.
-.SP
-This effect supports the \fB\-\-plot\fR global option.
-.TP
-\fBkey \fR[\fB\-q\fR] \fIshift\fR [\fIsegment\fR [\fIsearch\fR [\fIoverlap\fR]]]
-Change the audio key (i.e. pitch but not tempo).
-This is just an alias for the
-.B pitch
-effect.
-.TP
-\fBpan \fIdirection\fR
-Mix the audio from one channel to another.
-Use
-.B mixer
-or
-.B remix
-instead of this effect.
-.SP
-The
-.I direction
-is a value from \-1 to 1.  \-1 represents
-far left and 1 represents far right.
-.PP
-\fBpolyphase\fR [\fB\-w nut\fR\^|\^\fBham\fR] [\fB\-width \fIn\fR] [\fB\-cut-off \fIc\fR]
-.br
-\fBrabbit\fR [\fB\-c0\fR\^|\^\fB\-c1\fR\^|\^\fB\-c2\fR\^|\^\fB\-c3\fR\^|\^\fB\-c4\fR]
-.br
-\fBresample\fR [\fB\-qs\fR\^|\^\fB\-q\fR\^|\^\fB\-ql\fR] [\fIrolloff\fR [\fIbeta\fR]]
-.if t .sp -.5
-.if n .sp -1
-.TP
-\ 
-Formerly sample-rate-changing effects in their own right, these are now just aliases for the
-.B rate
-effect.
 .SH DIAGNOSTICS
 Exit status is 0 for no error, 1 if there is a problem with the
 command-line parameters, or 2 if an error occurs during file processing.
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -23,16 +23,16 @@
 # Format with: !xargs echo|tr ' ' '\n'|sort|column|expand|sed 's/^/  /'
 set(effects_srcs
   bend            dither          gain            phaser          stat
-  biquad          divide          input           rate            stats
-  biquads         earwax          loudness        remix           stretch
-  chorus          echo            mcompand        repeat          swap
-  compand         echos           mixer           reverb          synth
-  compandt        fade            noiseprof       reverse         tempo
-  contrast        fft4g           noisered        silence         tremolo
-  crop            filter          output          sinc            trim
-  dcshift         fir             overdrive       skeleff         upsample
-  delay           firfit          pad             speed           vad
-  dft_filter      flanger         pan             splice          vol
+  biquad          divide          hilbert         rate            stats
+  biquads         downsample      input           remix           stretch
+  chorus          earwax          loudness        repeat          swap
+  compand         echo            mcompand        reverb          synth
+  compandt        echos           mixer           reverse         tempo
+  contrast        fade            noiseprof       silence         tremolo
+  crop            fft4g           noisered        sinc            trim
+  dcshift         fir             output          skeleff         upsample
+  delay           firfit          overdrive       speed           vad
+  dft_filter      flanger         pad             splice          vol
 )
 set(formats_srcs
   8svx            dat             htk             s2-fmt          u2-fmt
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,16 +68,17 @@
 libsox_la_SOURCES += \
 	band.h bend.c biquad.c biquad.h biquads.c chorus.c compand.c crop.c \
 	compandt.c compandt.h contrast.c dcshift.c delay.c dft_filter.c \
-	dft_filter.h dither.c dither.h divide.c earwax.c echo.c \
-	echos.c effects.c effects.h effects_i.c effects_i_dsp.c fade.c fft4g.c \
-	fft4g.h fifo.h filter.c fir.c firfit.c flanger.c gain.c input.c \
-	ladspa.h ladspa.c loudness.c mcompand.c mcompand_xover.h mixer.c \
-	noiseprof.c noisered.c noisered.h output.c overdrive.c pad.c pan.c \
-	phaser.c rate.c rate_filters.h rate_half_fir.h rate_poly_fir0.h \
-	rate_poly_fir.h remix.c repeat.c reverb.c reverse.c silence.c \
-	sinc.c skeleff.c speed.c speexdsp.c splice.c stat.c stats.c \
-	stretch.c swap.c synth.c tempo.c tremolo.c trim.c vad.c vol.c \
-	ignore-warning.h upsample.c hilbert.c
+	dft_filter.h dither.c dither.h divide.c downsample.c earwax.c \
+	echo.c echos.c effects.c effects.h effects_i.c effects_i_dsp.c \
+	fade.c fft4g.c fft4g.h fifo.h fir.c firfit.c flanger.c gain.c \
+	hilbert.c input.c ladspa.h ladspa.c loudness.c mcompand.c \
+	mcompand_xover.h mixer.c noiseprof.c noisered.c \
+	noisered.h output.c overdrive.c pad.c phaser.c rate.c \
+	rate_filters.h rate_half_fir.h rate_poly_fir0.h rate_poly_fir.h \
+	remix.c repeat.c reverb.c reverse.c silence.c sinc.c skeleff.c \
+	speed.c speexdsp.c splice.c stat.c stats.c stretch.c swap.c \
+	synth.c tempo.c tremolo.c trim.c upsample.c vad.c vol.c \
+	ignore-warning.h
 if HAVE_PNG
     libsox_la_SOURCES += spectrogram.c
 endif
--- a/src/dither.c
+++ b/src/dither.c
@@ -329,7 +329,7 @@
   priv_t * p = (priv_t *)effp->priv;
   int c;
   lsx_getopt_t optstate;
-  lsx_getopt_init(argc, argv, "+aSsf:rt", NULL, lsx_getopt_flag_none, 1, &optstate);
+  lsx_getopt_init(argc, argv, "+aSsf:p:rt", NULL, lsx_getopt_flag_none, 1, &optstate);
 
   while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
     case 'a': p->auto_detect = sox_true; break;
@@ -341,6 +341,7 @@
       if (p->filter_name == INT_MAX)
         return SOX_EOF;
       break;
+    GETOPT_NUMERIC(optstate, 'p', prec, 1, 24)
     default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
   }
   argc -= optstate.ind, argv += optstate.ind;
@@ -353,10 +354,12 @@
   priv_t * p = (priv_t *)effp->priv;
   double mult = 1; /* Amount the noise shaping multiplies up the TPDF (+/-1) */
 
-  p->prec = effp->out_signal.precision;
+  if (p->prec == 0)
+    p->prec = effp->out_signal.precision;
+
   if (effp->in_signal.precision <= p->prec || p->prec > 24)
     return SOX_EFF_NULL;   /* Dithering not needed at this resolution */
-  effp->out_signal.precision = effp->in_signal.precision;
+  effp->out_signal.precision = p->prec;
 
   p->flow = flow_no_shape;
   if (p->filter_name) {
@@ -404,14 +407,15 @@
 sox_effect_handler_t const * lsx_dither_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "dither", "[-a] [-S|-s|-f filter]"
+    "dither", "[-S|-s|-f filter] [-a] [-p precision]"
     "\n  (none)   Use TPDF"
-    "\n  -a       Automatically turn on & off dithering as needed (use with caution!)"
     "\n  -S       Use sloped TPDF (without noise shaping)"
     "\n  -s       Shape noise (with shibata filter)"
     "\n  -f name  Set shaping filter to one of: lipshitz, f-weighted,"
     "\n           modified-e-weighted, improved-e-weighted, gesemann,"
-    "\n           shibata, low-shibata, high-shibata.",
+    "\n           shibata, low-shibata, high-shibata."
+    "\n  -a       Automatically turn on & off dithering as needed (use with caution!)"
+    "\n  -p bits  Override the target sample precision",
     SOX_EFF_PREC, getopts, start, flow, 0, 0, 0, sizeof(priv_t)
   };
   return &handler;
--- /dev/null
+++ b/src/downsample.c
@@ -1,0 +1,85 @@
+/* libSoX effect: Downsample
+ *
+ * First version of this effect written 11/2011 by Ulrich Klauer.
+ *
+ * Copyright 2011 Chris Bagwell and SoX Contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "sox_i.h"
+
+typedef struct {
+  unsigned int factor;
+  unsigned int carry; /* number of samples still to be discarded,
+                         carried over from last block */
+} priv_t;
+
+static int create(sox_effect_t *effp, int argc, char **argv)
+{
+  priv_t *p = (priv_t*)effp->priv;
+  p->factor = 2;
+  --argc, ++argv;
+  do { /* break-able block */
+    NUMERIC_PARAMETER(factor, 1, 16384)
+  } while (0);
+  return argc ? lsx_usage(effp) : SOX_SUCCESS;
+}
+
+static int start(sox_effect_t *effp)
+{
+  priv_t *p = (priv_t*) effp->priv;
+  effp->out_signal.rate = effp->in_signal.rate / p->factor;
+  return p->factor == 1 ? SOX_EFF_NULL : SOX_SUCCESS;
+}
+
+static int flow(sox_effect_t *effp, const sox_sample_t *ibuf,
+    sox_sample_t *obuf, size_t *isamp, size_t *osamp)
+{
+  priv_t *p = (priv_t*)effp->priv;
+  size_t ilen = *isamp, olen = *osamp;
+  size_t t;
+
+  t = min(p->carry, ilen);
+  p->carry -= t;
+  ibuf += t; ilen -= t;
+
+  /* NB: either p->carry (usually) or ilen is now zero; hence, a
+     non-zero value of ilen implies p->carry == 0, and there is no
+     need to test for this in the following while and if. */
+
+  while (ilen >= p->factor && olen) {
+    *obuf++ = *ibuf;
+    ibuf += p->factor;
+    olen--; ilen -= p->factor;
+  }
+
+  if (ilen && olen) {
+    *obuf++ = *ibuf;
+    p->carry = p->factor - ilen;
+    olen--; ilen = 0;
+  }
+
+  *isamp -= ilen, *osamp -= olen;
+  return SOX_SUCCESS;
+}
+
+sox_effect_handler_t const *lsx_downsample_effect_fn(void)
+{
+  static sox_effect_handler_t handler = {"downsample", "[factor (2)]",
+    SOX_EFF_RATE | SOX_EFF_MODIFY,
+    create, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
+  return &handler;
+}
--- a/src/effects.h
+++ b/src/effects.h
@@ -33,12 +33,12 @@
   EFFECT(dft_filter) /* abstract */
   EFFECT(dither)
   EFFECT(divide)
+  EFFECT(downsample)
   EFFECT(earwax)
   EFFECT(echo)
   EFFECT(echos)
   EFFECT(equalizer)
   EFFECT(fade)
-  EFFECT(filter)
   EFFECT(fir)
   EFFECT(firfit)
   EFFECT(flanger)
@@ -46,7 +46,6 @@
   EFFECT(highpass)
   EFFECT(hilbert)
   EFFECT(input)
-  EFFECT(key)
 #ifdef HAVE_LADSPA_H
   EFFECT(ladspa)
 #endif
@@ -61,15 +60,11 @@
   EFFECT(output)
   EFFECT(overdrive)
   EFFECT(pad)
-  EFFECT(pan)
   EFFECT(phaser)
   EFFECT(pitch)
-  EFFECT(polyphase)
-  EFFECT(rabbit)
   EFFECT(rate)
   EFFECT(remix)
   EFFECT(repeat)
-  EFFECT(resample)
   EFFECT(reverb)
   EFFECT(reverse)
   EFFECT(riaa)
--- a/src/fade.c
+++ b/src/fade.c
@@ -48,6 +48,7 @@
     char t_char[2];
     int t_argno;
     size_t samples;
+    const char *n;
   --argc, ++argv;
 
     if (argc < 1 || argc > 4)
@@ -75,7 +76,8 @@
     fade->in_stop_str = lsx_malloc(strlen(argv[0])+1);
     strcpy(fade->in_stop_str,argv[0]);
     /* Do a dummy parse to see if it will fail */
-    if (lsx_parsesamples(0., fade->in_stop_str, &samples, 't') == NULL)
+    n = lsx_parsesamples(0., fade->in_stop_str, &samples, 't');
+    if (!n || *n)
       return lsx_usage(effp);
 
     fade->in_stop = samples;
@@ -90,8 +92,8 @@
             strcpy(fade->out_stop_str,argv[t_argno]);
 
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., fade->out_stop_str,
-                                &samples, 't') == NULL)
+            n = lsx_parsesamples(0., fade->out_stop_str, &samples, 't');
+            if (!n || *n)
               return lsx_usage(effp);
             fade->out_stop = samples;
         }
@@ -101,8 +103,8 @@
             strcpy(fade->out_start_str,argv[t_argno]);
 
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., fade->out_start_str,
-                                &samples, 't') == NULL)
+            n = lsx_parsesamples(0., fade->out_start_str, &samples, 't');
+            if (!n || *n)
               return lsx_usage(effp);
             fade->out_start = samples;
         }
--- a/src/filter.c
+++ /dev/null
@@ -1,444 +1,0 @@
-/* libSoX Windowed sinc lowpass/bandpass/highpass filter     November 18, 1999
- * Copyright 1999 Stan Brooks <stabro@megsinet.net>
- * Copyright 1994 Julius O. Smith
- * Copyright 1991 (?) Lance Norskog (?)
- *
- * 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
- *
- *
- * REMARKS: (Stan Brooks speaking)
- * This code is a rewrite of filterkit.c from the `resample' package
- * by Julius O. Smith, now distributed under the LGPL.
- */
-
-#include "sox_i.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-#define ISCALE 0x10000
-#define BUFFSIZE 8192
-#define MAXNWING  (80<<7)
-
-/* Private data for Lerp via LCM file */
-typedef struct {
-        sox_rate_t rate;
-        double freq0;/* low  corner freq */
-        double freq1;/* high corner freq */
-        double beta;/* >2 is kaiser window beta, <=2 selects nuttall window */
-        long Nwin;
-        double *Fp;/* [Xh+1] Filter coefficients */
-        long Xh;/* number of past/future samples needed by filter  */
-        long Xt;/* target to enter new data into X */
-        double *X, *Y;/* I/O buffers */
-} priv_t;
-
-/* lsx_makeFilter is used by resample.c */
-int lsx_makeFilter(double Fp[], long Nwing, double Froll, double Beta, long Num, int Normalize);
-
-/* LpFilter()
- *
- * reference: "Digital Filters, 2nd edition"
- *            R.W. Hamming, pp. 178-179
- *
- * LpFilter() computes the coeffs of a Kaiser-windowed low pass filter with
- *    the following characteristics:
- *
- *       c[]  = array in which to store computed coeffs
- *       frq  = roll-off frequency of filter
- *       N    = Half the window length in number of coeffs
- *       Beta = parameter of Kaiser window
- *       Num  = number of coeffs before 1/frq
- *
- * Beta trades the rejection of the lowpass filter against the transition
- *    width from passband to stopband.  Larger Beta means a slower
- *    transition and greater stopband rejection.  See Rabiner and Gold
- *    (Theory and Application of DSP) under Kaiser windows for more about
- *    Beta.  The following table from Rabiner and Gold gives some feel
- *    for the effect of Beta:
- *
- * All ripples in dB, width of transition band = D*N where N = window length
- *
- *               BETA    D       PB RIP   SB RIP
- *               2.120   1.50  +-0.27      -30
- *               3.384   2.23    0.0864    -40
- *               4.538   2.93    0.0274    -50
- *               5.658   3.62    0.00868   -60
- *               6.764   4.32    0.00275   -70
- *               7.865   5.0     0.000868  -80
- *               8.960   5.7     0.000275  -90
- *               10.056  6.4     0.000087  -100
- */
-
-
-static void LpFilter(double *c, long N, double frq, double Beta, long Num)
-{
-   long i;
-
-   /* Calculate filter coeffs: */
-   c[0] = frq;
-   for (i=1; i<N; i++) {
-      double x = M_PI*(double)i/(double)(Num);
-      c[i] = sin(x*frq)/x;
-   }
-
-   if (Beta>2) { /* Apply Kaiser window to filter coeffs: */
-      double IBeta = 1.0/lsx_bessel_I_0(Beta);
-      for (i=1; i<N; i++) {
-         double x = (double)i / (double)(N-1);
-         c[i] *= lsx_bessel_I_0(Beta*sqrt(1.0-x*x)) * IBeta;
-      }
-   } else { /* Apply Nuttall window: */
-      for(i = 0; i < N; i++) {
-         double x = M_PI*i / N;
-         c[i] *= 0.3635819 + 0.4891775*cos(x) + 0.1365995*cos(2*x) + 0.0106411*cos(3*x);
-      }
-   }
-}
-
-int lsx_makeFilter(double Imp[], long Nwing, double Froll, double Beta,
-               long Num, int Normalize)
-{
-   double *ImpR;
-   long Mwing, i;
-
-   if (Nwing > MAXNWING)                      /* Check for valid parameters */
-      return(-1);
-   if ((Froll<=0) || (Froll>1))
-      return(-2);
-
-   /* it does help accuracy a bit to have the window stop at
-    * a zero-crossing of the sinc function */
-   Mwing = floor((double)Nwing/(Num/Froll))*(Num/Froll) +0.5;
-   if (Mwing==0)
-      return(-4);
-
-   ImpR = lsx_malloc(sizeof(double) * Mwing);
-
-   /* Design a Nuttall or Kaiser windowed Sinc low-pass filter */
-   LpFilter(ImpR, Mwing, Froll, Beta, Num);
-
-   if (Normalize) { /* 'correct' the DC gain of the lowpass filter */
-      long Dh;
-      double DCgain;
-      DCgain = 0;
-      Dh = Num;                  /* Filter sampling period for factors>=1 */
-      for (i=Dh; i<Mwing; i+=Dh)
-         DCgain += ImpR[i];
-      DCgain = 2*DCgain + ImpR[0];    /* DC gain of real coefficients */
-      lsx_debug("DCgain err=%.12f",DCgain-1.0);
-
-      DCgain = 1.0/DCgain;
-      for (i=0; i<Mwing; i++)
-         Imp[i] = ImpR[i]*DCgain;
-
-   } else {
-      for (i=0; i<Mwing; i++)
-         Imp[i] = ImpR[i];
-   }
-   free(ImpR);
-   for (i=Mwing; i<=Nwing; i++) Imp[i] = 0;
-   /* Imp[Mwing] and Imp[-1] needed for quadratic interpolation */
-   Imp[-1] = Imp[1];
-
-   return(Mwing);
-}
-
-static void FiltWin(priv_t * f, long Nx);
-
-/*
- * Process options
- */
-static int sox_filter_getopts(sox_effect_t * effp, int argc, char **argv)
-{
-        priv_t * f = (priv_t *) effp->priv;
-  --argc, ++argv;
-
-        f->beta = 16;  /* Kaiser window, beta 16 */
-        f->Nwin = 128;
-
-        f->freq0 = f->freq1 = 0;
-        if (argc >= 1) {
-                char *p;
-                p = argv[0];
-                if (*p != '-') {
-                        f->freq1 = lsx_parse_frequency(p, &p);
-                }
-                if (*p == '-') {
-                        f->freq0 = f->freq1;
-                        f->freq1 = lsx_parse_frequency(p+1, &p);
-                }
-                if (*p) f->freq1 = f->freq0 = 0;
-        }
-        lsx_debug("freq: %g-%g", f->freq0, f->freq1);
-        if (f->freq0 == 0 && f->freq1 == 0)
-          return lsx_usage(effp);
-
-        if ((argc >= 2) && !sscanf(argv[1], "%ld", &f->Nwin))
-          return lsx_usage(effp);
-        else if (f->Nwin < 4) {
-                lsx_fail("filter: window length (%ld) <4 is too short", f->Nwin);
-                return (SOX_EOF);
-        }
-
-        if ((argc >= 3) && !sscanf(argv[2], "%lf", &f->beta))
-          return lsx_usage(effp);
-
-        lsx_debug("filter opts: %g-%g, window-len %ld, beta %f", f->freq0, f->freq1, f->Nwin, f->beta);
-        return (SOX_SUCCESS);
-}
-
-/*
- * Prepare processing.
- */
-static int sox_filter_start(sox_effect_t * effp)
-{
-        priv_t * f = (priv_t *) effp->priv;
-        double *Fp0, *Fp1;
-        long Xh0, Xh1, Xh;
-        int i;
-
-        f->rate = effp->in_signal.rate;
-
-        /* adjust upper frequency to Nyquist if necessary */
-        if (f->freq1 > (sox_sample_t)f->rate/2 || f->freq1 <= 0)
-                f->freq1 = f->rate/2;
-
-        if ((f->freq0 < 0) || (f->freq0 > f->freq1))
-        {
-                lsx_fail("filter: low(%g),high(%g) parameters must satisfy 0 <= low <= high <= %g",
-                                        f->freq0, f->freq1, f->rate/2);
-                return (SOX_EOF);
-        }
-
-        Xh = f->Nwin/2;
-        Fp0 = lsx_malloc(sizeof(double) * (Xh + 2));
-        ++Fp0;
-        if (f->freq0 > (sox_sample_t)f->rate/200) {
-                Xh0 = lsx_makeFilter(Fp0, Xh, 2.0*(double)f->freq0/f->rate, f->beta, (size_t) 1, 0);
-                if (Xh0 <= 1)
-                {
-                        lsx_fail("filter: Unable to make low filter");
-                        return (SOX_EOF);
-                }
-        } else {
-                Xh0 = 0;
-        }
-        Fp1 = lsx_malloc(sizeof(double) * (Xh + 2));
-        ++Fp1;
-        /* need Fp[-1] and Fp[Xh] for lsx_makeFilter */
-        if (f->freq1 < (sox_sample_t)f->rate/2) {
-                Xh1 = lsx_makeFilter(Fp1, Xh, 2.0*(double)f->freq1/f->rate, f->beta, (size_t) 1, 0);
-                if (Xh1 <= 1)
-                {
-                        lsx_fail("filter: Unable to make high filter");
-                        return (SOX_EOF);
-                }
-        } else {
-                Fp1[0] = 1.0;
-                Xh1 = 1;
-        }
-        /* now subtract Fp0[] from Fp1[] */
-        Xh = (Xh0>Xh1)?  Xh0:Xh1; /* >=1, by above */
-        for (i=0; i<Xh; i++) {
-                double c0,c1;
-                c0 = (i<Xh0)? Fp0[i]:0;
-                c1 = (i<Xh1)? Fp1[i]:0;
-                Fp1[i] = c1-c0;
-        }
-
-        free(Fp0 - 1); /* all done with Fp0 */
-        f->Fp = Fp1;
-
-        Xh -= 1;       /* Xh = 0 can only happen if filter was identity 0-Nyquist */
-        if (Xh<=0)
-                lsx_warn("filter: adjusted freq %g-%g is identity", f->freq0, f->freq1);
-
-        f->Nwin = 2*Xh + 1;  /* not really used afterwards */
-        f->Xh = Xh;
-        f->Xt = Xh;
-
-   if (effp->global_info->plot != sox_plot_off) {
-     int n = 2 * Xh + 1;
-     double * h = lsx_malloc(n * sizeof(*h));
-     char title[100];
-     sprintf(title, "SoX effect: filter frequency=%g-%g", f->freq0, f->freq1);
-     for (i = 1; i < Xh + 1; ++i)
-       h[i - 1] = f->Fp[Xh + 1 - i];
-     for (i = 0; i < Xh + 1; ++i)
-       h[Xh + i] = f->Fp[i];
-     lsx_plot_fir(h, n, effp->in_signal.rate, effp->global_info->plot, title, -f->beta * 10 - 20, 10.);
-     free(h);
-     return SOX_EOF;
-   }
-
-        f->X = lsx_malloc(sizeof(double) * (2*BUFFSIZE + 2*Xh));
-        f->Y = f->X + BUFFSIZE + 2*Xh;
-
-        /* Need Xh zeros at beginning of X */
-        for (i = 0; i < Xh; i++)
-                f->X[i] = 0;
-        return (SOX_SUCCESS);
-}
-
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
-static int sox_filter_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
-                   size_t *isamp, size_t *osamp)
-{
-        priv_t * f = (priv_t *) effp->priv;
-        size_t Nx;
-        long i, Nproc;
-
-        /* constrain amount we actually process */
-        /* lsx_debug("Xh %d, Xt %d, isamp %d, ",f->Xh, f->Xt, *isamp); */
-        Nx = BUFFSIZE + 2*f->Xh - f->Xt;
-        if (Nx > *isamp) Nx = *isamp;
-        if (Nx > *osamp) Nx = *osamp;
-        *isamp = Nx;
-
-        {
-                double *xp, *xtop;
-                xp = f->X + f->Xt;
-                xtop = xp + Nx;
-                if (ibuf != NULL) {
-                        while (xp < xtop)
-                                *xp++ = (double)(*ibuf++) / ISCALE;
-                } else {
-                        while (xp < xtop)
-                                *xp++ = 0;
-                }
-        }
-
-        Nproc = f->Xt + Nx - 2*f->Xh;
-
-        if (Nproc <= 0) {
-                f->Xt += Nx;
-                *osamp = 0;
-                return (SOX_SUCCESS);
-        }
-        lsx_debug("flow Nproc %ld",Nproc);
-        FiltWin(f, Nproc);
-
-        /* Copy back portion of input signal that must be re-used */
-        Nx += f->Xt;
-        if (f->Xh)
-                memmove(f->X, f->X + Nx - 2*f->Xh, sizeof(double)*2*f->Xh);
-        f->Xt = 2*f->Xh;
-
-        for (i = 0; i < Nproc; i++)
-                *obuf++ = f->Y[i] * ISCALE;
-
-        *osamp = Nproc;
-        return (SOX_SUCCESS);
-}
-
-/*
- * Process tail of input samples.
- */
-static int sox_filter_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
-{
-        priv_t * f = (priv_t *) effp->priv;
-        long isamp_res, osamp_res;
-        sox_sample_t *Obuf;
-
-        lsx_debug("Xh %ld, Xt %ld  <--- DRAIN",f->Xh, f->Xt);
-
-        /* stuff end with Xh zeros */
-        isamp_res = f->Xh;
-        osamp_res = *osamp;
-        Obuf = obuf;
-        while (isamp_res>0 && osamp_res>0) {
-                size_t Isamp, Osamp;
-                Isamp = isamp_res;
-                Osamp = osamp_res;
-                sox_filter_flow(effp, NULL, Obuf, &Isamp, &Osamp);
-          /* lsx_debug("DRAIN isamp,osamp  (%d,%d) -> (%d,%d)",
-                 * isamp_res,osamp_res,Isamp,Osamp); */
-                Obuf += Osamp;
-                osamp_res -= Osamp;
-                isamp_res -= Isamp;
-        };
-        *osamp -= osamp_res;
-        /* lsx_debug("DRAIN osamp %d", *osamp); */
-        if (isamp_res)
-                lsx_warn("drain overran obuf by %ld", isamp_res);
-        /* FIXME: This is very picky. osamp better be big enough to grab
-         * all remaining samples or they will be discarded.
-         */
-        return (SOX_EOF);
-}
-
-/*
- * Do anything required when you stop reading samples.
- * Don't close input file!
- */
-static int sox_filter_stop(sox_effect_t * effp)
-{
-        priv_t * f = (priv_t *) effp->priv;
-
-        free(f->Fp - 1);
-        free(f->X);
-        return (SOX_SUCCESS);
-}
-
-static double jprod(const double *Fp, const double *Xp, long ct)
-{
-        const double *fp, *xp, *xq;
-        double v = 0;
-
-        fp = Fp + ct;   /* so sum starts with smaller coef's */
-        xp = Xp - ct;
-        xq = Xp + ct;
-        while (fp > Fp) {   /* ct = 0 can happen */
-                v += *fp * (*xp + *xq);
-                xp++; xq--; fp--;
-        }
-        v += *fp * *xp;
-        return v;
-}
-
-static void FiltWin(priv_t * f, long Nx)
-{
-        double *Y;
-        double *X, *Xend;
-
-        Y = f->Y;
-        X = f->X + f->Xh;                       /* Ptr to current input sample */
-        Xend = X + Nx;
-        while (X < Xend) {
-                *Y++ = jprod(f->Fp, X, f->Xh);
-                X++;
-        }
-}
-
-static sox_effect_handler_t sox_filter_effect = {
-  "filter",
-  "low-high [ windowlength [ beta ] ]",
-  SOX_EFF_DEPRECATED,
-  sox_filter_getopts,
-  sox_filter_start,
-  sox_filter_flow,
-  sox_filter_drain,
-  sox_filter_stop,
-  NULL, sizeof(priv_t)
-};
-
-const sox_effect_handler_t *lsx_filter_effect_fn(void)
-{
-    return &sox_filter_effect;
-}
--- a/src/fir.c
+++ b/src/fir.c
@@ -34,7 +34,9 @@
 
   b->filter_ptr = &b->filter;
   --argc, ++argv;
-  if (argc == 1)
+  if (!argc)
+    p->filename = "-"; /* default to stdin */
+  else if (argc == 1)
     p->filename = argv[0], --argc;
   else for (; argc && sscanf(*argv, "%lf%c", &d, &c) == 1; --argc, ++argv) {
     p->n++;
@@ -57,12 +59,16 @@
       FILE * file = lsx_open_input_file(effp, p->filename);
       if (!file)
         return SOX_EOF;
-      while (fscanf(file, " #%*[^\n]%c", &c) + (i = fscanf(file, "%lf", &d)) >0)
-        if (i > 0) {
+      while ((i = fscanf(file, " #%*[^\n]%c", &c)) >= 0) {
+        if (i >= 1) continue; /* found and skipped a comment */
+        if ((i = fscanf(file, "%lf", &d)) > 0) {
+          /* found a coefficient value */
           p->n++;
           p->h = lsx_realloc(p->h, p->n * sizeof(*p->h));
           p->h[p->n - 1] = d;
-        }
+        } else break; /* either EOF, or something went wrong
+                         (read or syntax error) */
+      }
       if (!feof(file)) {
         lsx_fail("error reading coefficient file");
         if (file != stdin) fclose(file);
@@ -73,6 +79,14 @@
     lsx_report("%i coefficients", p->n);
     if (!p->n)
       return SOX_EFF_NULL;
+    if (effp->global_info->plot != sox_plot_off) {
+      char title[100];
+      sprintf(title, "SoX effect: fir (%d coefficients)", p->n);
+      lsx_plot_fir(p->h, p->n, effp->in_signal.rate,
+          effp->global_info->plot, title, -30., 30.);
+      free(p->h);
+      return SOX_EOF;
+    }
     lsx_set_dft_filter(f, p->h, p->n, p->n >> 1);
   }
   return lsx_dft_filter_effect_fn()->start(effp);
--- a/src/gain.c
+++ b/src/gain.c
@@ -251,16 +251,10 @@
 static int norm_getopts(sox_effect_t * effp, int argc, char * * argv)
 {
   char * argv2[3];
-  int argc2 = 0;
+  int argc2 = 2;
 
-  argv2[argc2++] = argv[0], --argc, ++argv;
-  if (argc && !strcmp(*argv, "-i"))
-    argv2[argc2++] = "-en", --argc, ++argv;
-  else if (argc && !strcmp(*argv, "-b"))
-    argv2[argc2++] = "-B", --argc, ++argv;
-  if (argc2 > 1)
-    lsx_warn("this usage is deprecated; use `gain %s' instead", argv2[1]);
-  else argv2[argc2++] = "-n";
+  argv2[0] = argv[0], --argc, ++argv;
+  argv2[1] = "-n";
   if (argc)
     argv2[argc2++] = *argv, --argc, ++argv;
   return argc? lsx_usage(effp) :
--- a/src/hilbert.c
+++ b/src/hilbert.c
@@ -59,9 +59,9 @@
   if (!f->num_taps) {
     int i;
     if (!p->taps) {
-      p->taps = effp->in_signal.rate/100 + 2;
+      p->taps = effp->in_signal.rate/76.5 + 2;
       p->taps += 1 - (p->taps%2);
-      /* results in a cutoff frequency of about 75 Hz */
+      /* results in a cutoff frequency of about 75 Hz with a Blackman window */
       lsx_debug("choosing number of taps = %d (override with -n)", p->taps);
     }
     lsx_valloc(p->h, p->taps);
@@ -74,7 +74,7 @@
         p->h[i] = (1 - cos(pk))/pk;
       }
     }
-    lsx_apply_hamming(p->h, p->taps);
+    lsx_apply_blackman(p->h, p->taps, .16);
 
     if (effp->global_info->plot != sox_plot_off) {
       char title[100];
--- a/src/ima_rw.c
+++ b/src/ima_rw.c
@@ -252,16 +252,15 @@
         int opt             /* non-zero allows some cpu-intensive code to improve output */
 )
 {
-        int snext,d;
+        int snext;
         int s0,d0;
-        int s32,d32;
 
-        s32 = s0 = *st;
+        s0 = *st;
         if (opt>0) {
                 int low,hi,w;
                 int low0,hi0;
                 snext = s0;
-                d32 = d0 = ImaMashS(ch, chans, ip[0], ip,n,&snext, NULL);
+                d0 = ImaMashS(ch, chans, ip[0], ip,n,&snext, NULL);
 
                 w = 0;
                 low=hi=s0;
@@ -292,7 +291,7 @@
                 }
                 *st = s0;
         }
-        d = ImaMashS(ch, chans, ip[0], ip,n,st, obuff);
+        ImaMashS(ch, chans, ip[0], ip,n,st, obuff);
 }
 
 /* mash one block.  if you want to use opt>0, 9 is a reasonable value */
--- a/src/pan.c
+++ /dev/null
@@ -1,426 +1,0 @@
-/* (c) 20/03/2000 Fabien COELHO <fabien@coelho.net> for sox.
- *
- * 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
- *
- * Change panorama of sound file with basic linear volume interpolation.
- * The human ear is not sensible to phases? What about delay? too short?
- *
- * Volume is kept constant (?).
- * Beware of saturations!
- * Operations are carried out on doubles.
- * Can handle different number of channels.
- * Cannot handle rate change.
- *
- * Initially based on avg effect.
- * pan 0.0 basically behaves as avg.
- */
-
-#include "sox_i.h"
-#include <string.h>
-
-/* structure to hold pan parameter */
-
-typedef struct {double direction;} priv_t; /* from left (-1.0) to right (1.0) */
-
-/*
- * Process options
- */
-static int sox_pan_getopts(sox_effect_t * effp, int argc, char **argv)
-{
-    priv_t * pan = (priv_t *) effp->priv;
-  --argc, ++argv;
-
-    pan->direction = 0.0; /* default is no change */
-
-    if (argc && (!sscanf(argv[0], "%lf", &pan->direction) ||
-              pan->direction < -1.0 || pan->direction > 1.0))
-      return lsx_usage(effp);
-
-    return SOX_SUCCESS;
-}
-
-/*
- * Start processing
- */
-static int sox_pan_start(sox_effect_t * effp)
-{
-    if (effp->out_signal.channels==1)
-        lsx_warn("PAN onto a mono channel...");
-    return SOX_SUCCESS;
-}
-
-
-#define UNEXPECTED_CHANNELS \
-    lsx_fail("unexpected number of channels (in=%d, out=%d)", ich, och); \
-    free(ibuf_copy); \
-    return SOX_EOF
-
-/*
- * Process either isamp or osamp samples, whichever is smaller.
- */
-static int sox_pan_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
-                size_t *isamp, size_t *osamp)
-{
-    priv_t * pan = (priv_t *) effp->priv;
-    size_t len, done;
-    sox_sample_t *ibuf_copy;
-    char ich, och;
-    double left, right, direction, hdir;
-
-    ibuf_copy = lsx_malloc(*isamp * sizeof(sox_sample_t));
-    memcpy(ibuf_copy, ibuf, *isamp * sizeof(sox_sample_t));
-
-    direction   = pan->direction;    /* -1   <=  direction  <= 1   */
-    hdir  = 0.5 * direction;  /* -0.5 <=  hdir <= 0.5 */
-    left  = 0.5 - hdir; /*  0   <=  left <= 1   */
-    right = 0.5 + hdir; /*  0   <= right <= 1   */
-
-    ich = effp->in_signal.channels;
-    och = effp->out_signal.channels;
-
-    len = min(*osamp/och,*isamp/ich);
-
-    /* report back how much is processed. */
-    *isamp = len*ich;
-    *osamp = len*och;
-
-    /* 9 different cases to handle: (1,2,4) X (1,2,4) */
-    switch (och) {
-    case 1: /* pan on mono channel... not much sense. just avg. */
-        switch (ich) {
-        case 1: /* simple copy */
-            for (done=0; done<len; done++)
-                *obuf++ = *ibuf_copy++;
-            break;
-        case 2: /* average 2 */
-            for (done=0; done<len; done++)
-            {
-                double f;
-                f = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[1];
-                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                *obuf++ = f;
-                ibuf_copy += 2;
-            }
-            break;
-        case 4: /* average 4 */
-            for (done=0; done<len; done++)
-            {
-                double f;
-                f = 0.25*ibuf_copy[0] + 0.25*ibuf_copy[1] +
-                        0.25*ibuf_copy[2] + 0.25*ibuf_copy[3];
-                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                *obuf++ = f;
-                ibuf_copy += 4;
-            }
-            break;
-        default:
-            UNEXPECTED_CHANNELS;
-            break;
-        } /* end first switch in channel */
-        break;
-    case 2:
-        switch (ich) {
-        case 1: /* linear */
-            for (done=0; done<len; done++)
-            {
-                double f;
-
-                f = left * ibuf_copy[0];
-                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                obuf[0] = f;
-                f = right * ibuf_copy[0];
-                SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                obuf[1] = f;
-                obuf += 2;
-                ibuf_copy++;
-            }
-            break;
-        case 2: /* linear panorama.
-                 * I'm not sure this is the right way to do it.
-                 */
-            if (direction <= 0.0) /* to the left */
-            {
-                register double volume, cll, clr, cr;
-
-                volume = 1.0 - 0.5*direction;
-                cll = volume*(1.5-left);
-                clr = volume*(left-0.5);
-                cr  = volume*(1.0+direction);
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cll * ibuf_copy[0] + clr * ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[0] = f;
-                    f = cr * ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[1] = f;
-                    obuf += 2;
-                    ibuf_copy += 2;
-                }
-            }
-            else /* to the right */
-            {
-                register double volume, cl, crl, crr;
-
-                volume = 1.0 + 0.5*direction;
-                cl  = volume*(1.0-direction);
-                crl = volume*(right-0.5);
-                crr = volume*(1.5-right);
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cl * ibuf_copy[0];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[0] = f;
-                    f = crl * ibuf_copy[0] + crr * ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[1] = f;
-                    obuf += 2;
-                    ibuf_copy += 2;
-                }
-            }
-            break;
-        case 4:
-            if (direction <= 0.0) /* to the left */
-            {
-                register double volume, cll, clr, cr;
-
-                volume = 1.0 - 0.5*direction;
-                cll = volume*(1.5-left);
-                clr = volume*(left-0.5);
-                cr  = volume*(1.0+direction);
-
-                for (done=0; done<len; done++)
-                {
-                    register double ibuf0, ibuf1, f;
-
-                    /* build stereo signal */
-                    ibuf0 = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[2];
-                    ibuf1 = 0.5*ibuf_copy[1] + 0.5*ibuf_copy[3];
-
-                    /* pan it */
-                    f = cll * ibuf0 + clr * ibuf1;
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[0] = f;
-                    f = cr * ibuf1;
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[1] = f;
-                    obuf += 2;
-                    ibuf_copy += 4;
-                }
-            }
-            else /* to the right */
-            {
-                register double volume, cl, crl, crr;
-
-                volume = 1.0 + 0.5*direction;
-                cl  = volume*(1.0-direction);
-                crl = volume*(right-0.5);
-                crr = volume*(1.5-right);
-
-                for (done=0; done<len; done++)
-                {
-                    register double ibuf0, ibuf1, f;
-
-                    ibuf0 = 0.5*ibuf_copy[0] + 0.5*ibuf_copy[2];
-                    ibuf1 = 0.5*ibuf_copy[1] + 0.5*ibuf_copy[3];
-
-                    f = cl * ibuf0;
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[0] = f;
-                    f = crl * ibuf0 + crr * ibuf1;
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[1] = f;
-                    obuf += 2;
-                    ibuf_copy += 4;
-                }
-            }
-            break;
-        default:
-            UNEXPECTED_CHANNELS;
-            break;
-        } /* end second switch in channel */
-        break;
-    case 4:
-        switch (ich) {
-        case 1: /* linear */
-            {
-                register double cr, cl;
-
-                cl = 0.5*left;
-                cr = 0.5*right;
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cl * ibuf_copy[0];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[2] = obuf[0] = f;
-                    f = cr * ibuf_copy[0];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    ibuf_copy[3] = obuf[1] = f;
-                    obuf += 4;
-                    ibuf_copy++;
-                }
-            }
-            break;
-        case 2: /* simple linear panorama */
-            if (direction <= 0.0) /* to the left */
-            {
-                register double volume, cll, clr, cr;
-
-                volume = 0.5 - 0.25*direction;
-                cll = volume * (1.5-left);
-                clr = volume * (left-0.5);
-                cr  = volume * (1.0+direction);
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cll * ibuf_copy[0] + clr * ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[2] = obuf[0] = f;
-                    f = cr * ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    ibuf_copy[3] = obuf[1] = f;
-                    obuf += 4;
-                    ibuf_copy += 2;
-                }
-            }
-            else /* to the right */
-            {
-                register double volume, cl, crl, crr;
-
-                volume = 0.5 + 0.25*direction;
-                cl  = volume * (1.0-direction);
-                crl = volume * (right-0.5);
-                crr = volume * (1.5-right);
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cl * ibuf_copy[0];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[2] = obuf[0] =f ;
-                    f = crl * ibuf_copy[0] + crr * ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    ibuf_copy[3] = obuf[1] = f;
-                    obuf += 4;
-                    ibuf_copy += 2;
-                }
-            }
-            break;
-        case 4:
-            /* maybe I could improve the formula to reverse...
-               also, turn only by quarters.
-             */
-            if (direction <= 0.0) /* to the left */
-            {
-                register double cown, cright;
-
-                cright = -direction;
-                cown = 1.0 + direction;
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cown*ibuf_copy[0] + cright*ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[0] = f;
-                    f = cown*ibuf_copy[1] + cright*ibuf_copy[3];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[1] = f;
-                    f = cown*ibuf_copy[2] + cright*ibuf_copy[0];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[2] = f;
-                    f = cown*ibuf_copy[3] + cright*ibuf_copy[2];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[3] = f;
-                    obuf += 4;
-                    ibuf_copy += 4;
-                }
-            }
-            else /* to the right */
-            {
-                register double cleft, cown;
-
-                cleft = direction;
-                cown = 1.0 - direction;
-
-                for (done=0; done<len; done++)
-                {
-                    double f;
-
-                    f = cleft*ibuf_copy[2] + cown*ibuf_copy[0];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[0] = f;
-                    f = cleft*ibuf_copy[0] + cown*ibuf_copy[1];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[1] = f;
-                    f = cleft*ibuf_copy[3] + cown*ibuf_copy[2];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[2] = f;
-                    f = cleft*ibuf_copy[1] + cown*ibuf_copy[3];
-                    SOX_SAMPLE_CLIP_COUNT(f, effp->clips);
-                    obuf[3] = f;
-                    obuf += 4;
-                    ibuf_copy += 4;
-                }
-            }
-            break;
-        default:
-            UNEXPECTED_CHANNELS;
-            break;
-        } /* end third switch in channel */
-        break;
-    default:
-        UNEXPECTED_CHANNELS;
-        break;
-    } /* end switch out channel */
-
-    free(ibuf_copy - len * ich);
-
-    return SOX_SUCCESS;
-}
-
-/*
- * FIXME: Add a stop function with statistics on right, left, and output amplitudes.
- */
-
-static sox_effect_handler_t sox_pan_effect = {
-  "pan",
-  "direction (in [-1.0 .. 1.0])",
-  SOX_EFF_MCHAN | SOX_EFF_CHAN | SOX_EFF_DEPRECATED,
-  sox_pan_getopts,
-  sox_pan_start,
-  sox_pan_flow,
-  NULL,
-  NULL,
-  NULL, sizeof(priv_t)
-};
-
-const sox_effect_handler_t *lsx_pan_effect_fn(void)
-{
-    return &sox_pan_effect;
-}
--- a/src/rate.c
+++ b/src/rate.c
@@ -558,125 +558,3 @@
   handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
   return &handler;
 }
-
-/*------------------- emulation of the old `rabbit' effect -------------------*/
-
-static int rabbit_getopts(sox_effect_t * effp, int argc, char * * argv)
-{
-  static char const * const qualities[] = {"-v", "-h", "-l", "-q", "-q"};
-  char quality[2] = "0", dummy;     /* To check for extraneous chars. */
-  char * args[] = {0, 0, 0};
-  int argc2 = 2;
-
-  if (argc > 1) {
-    int n = sscanf(argv[1], "-c%1[0-4] %c", quality, &dummy);
-    if (n > 1)
-      return lsx_usage(effp);
-    if (n == 1)
-      --argc, ++argv;
-  }
-
-  args[0] = argv[0];
-  args[1] = (char *)qualities[quality[0] - '0'];
-  if (argc > 1) {
-    args[2] = argv[1];
-    --argc, ++argv;
-    ++argc2;
-  }
-  return argc > 1? lsx_usage(effp) : 
-    lsx_rate_effect_fn()->getopts(effp, argc2, args);
-}
-
-sox_effect_handler_t const * lsx_rabbit_effect_fn(void)
-{
-  static sox_effect_handler_t handler;
-  handler = *lsx_rate_effect_fn();
-  handler.name = "rabbit";
-  handler.usage = "[-c0|-c1|-c2|-c3|-c4] [rate]";
-  handler.getopts = rabbit_getopts;
-  handler.flags |= SOX_EFF_DEPRECATED;
-  return &handler;
-}
-
-/*------------------ emulation of the old `polyphase' effect -----------------*/
-
-static int polyphase_getopts(sox_effect_t * effp, int argc, char * * argv)
-{
-  char arg[100], * args[] = {0, "-vb", 0};
-  double bandwidth = 95;
-
-  for (--argc, ++argv; argc >= 2; argc -= 2, argv += 2)
-    if (!strcmp(argv[0], "-cutoff"))
-      bandwidth = 100 * atof(argv[1]);
-    else if (strcmp(argv[0], "-w") && strcmp(argv[0], "-width")) {
-      lsx_fail("unknown parameter: %s %s", argv[0], argv[1]);
-      return SOX_EOF;
-    }
-  args[0] = argv[0];
-  args[2] = arg;
-  sprintf(arg, "%f", bandwidth);
-  return argc? lsx_usage(effp) : 
-    lsx_rate_effect_fn()->getopts(effp, (int)array_length(args), args);
-}
-
-sox_effect_handler_t const * lsx_polyphase_effect_fn(void)
-{
-  static sox_effect_handler_t handler;
-  handler = *lsx_rate_effect_fn();
-  handler.name = "polyphase";
-  handler.usage = "-cutoff factor    Cutoff frequency 0 to 1, default 0.95";
-  handler.getopts = polyphase_getopts;
-  handler.flags |= SOX_EFF_DEPRECATED;
-  return &handler;
-}
-
-/*------------------ emulation of the old `resample' effect ------------------*/
-
-static int resample_getopts(sox_effect_t * effp, int argc, char * * argv)
-{
-  char arg[100], * args[] = {0, 0, "-b", 0};
-  double bandwidth = .8;
-  char const * quality = NULL;
-
-  --argc, ++argv;
-  if (argc) {
-    if (!strcmp(argv[0], "-qs")) {
-      quality = "-h";
-      --argc, ++argv;
-    }
-    else if (!strcmp(argv[0], "-q")) {
-      bandwidth = .875;
-      quality = "-v";
-      --argc, ++argv;
-    }
-    else if (!strcmp(argv[0], "-ql")) {
-      bandwidth = .94;
-      quality = "-v";
-      --argc, ++argv;
-    }
-  }
-  if (argc) {
-    if (sscanf(argv[0], "%lf", &bandwidth) != 1)
-      return lsx_usage(effp);
-    if (!quality)
-      quality = "-m";
-  }
-
-  args[0] = argv[0];
-  args[1] = (char *)(quality? quality : "-l");
-  args[3] = arg;
-  sprintf(arg, "%f", 100 * bandwidth);
-  return argc > 2 ? lsx_usage(effp) : 
-    lsx_rate_effect_fn()->getopts(effp, quality? 4 : 2, args);
-}
-
-sox_effect_handler_t const * lsx_resample_effect_fn(void)
-{
-  static sox_effect_handler_t handler;
-  handler = *lsx_rate_effect_fn();
-  handler.name = "resample";
-  handler.usage = "[ -qs | -q | -ql ] [ rolloff [ beta ] ]",
-  handler.getopts = resample_getopts;
-  handler.flags |= SOX_EFF_DEPRECATED;
-  return &handler;
-}
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -21,7 +21,6 @@
 #include "fifo.h"
 
 #define lsx_zalloc(var, n) var = lsx_calloc(n, sizeof(*var))
-#define filter_create(p, n) (p)->ptr=lsx_zalloc((p)->buffer, (p)->size=(size_t)(n))
 #define filter_advance(p) if (--(p)->ptr < (p)->buffer) (p)->ptr += (p)->size
 #define filter_delete(p) free((p)->buffer)
 
@@ -69,14 +68,14 @@
   for (i = 0; i < array_length(comb_lengths); ++i, offset = -offset)
   {
     filter_t * pcomb = &p->comb[i];
-    double n = scale * r * (comb_lengths[i] + stereo_adjust * offset) + .5;
-    filter_create(pcomb, n);
+    pcomb->size = (size_t)(scale * r * (comb_lengths[i] + stereo_adjust * offset) + .5);
+    pcomb->ptr = lsx_zalloc(pcomb->buffer, pcomb->size);
   }
   for (i = 0; i < array_length(allpass_lengths); ++i, offset = -offset)
   {
     filter_t * pallpass = &p->allpass[i];
-    double n = r * (allpass_lengths[i] + stereo_adjust * offset) + .5;
-    filter_create(pallpass, n);
+    pallpass->size = (size_t)(r * (allpass_lengths[i] + stereo_adjust * offset) + .5);
+    pallpass->ptr = lsx_zalloc(pallpass->buffer, pallpass->size);
   }
 }
 
--- a/src/silence.c
+++ b/src/silence.c
@@ -80,6 +80,7 @@
 {
     priv_t *   silence = (priv_t *) effp->priv;
     int parse_count;
+    const char *n;
   --argc, ++argv;
 
     /* check for option switches */
@@ -120,8 +121,8 @@
         silence->start_duration_str = lsx_malloc(strlen(argv[0])+1);
         strcpy(silence->start_duration_str,argv[0]);
         /* Perform a fake parse to do error checking */
-        if (lsx_parsesamples(0.,silence->start_duration_str,
-                    &silence->start_duration,'s') == NULL)
+        n = lsx_parsesamples(0.,silence->start_duration_str,&silence->start_duration,'s');
+        if (!n || *n)
           return lsx_usage(effp);
 
         parse_count = sscanf(argv[1], "%lf%c", &silence->start_threshold,
@@ -161,8 +162,8 @@
         silence->stop_duration_str = lsx_malloc(strlen(argv[0])+1);
         strcpy(silence->stop_duration_str,argv[0]);
         /* Perform a fake parse to do error checking */
-        if (lsx_parsesamples(0.,silence->stop_duration_str,
-                    &silence->stop_duration,'s') == NULL)
+        n = lsx_parsesamples(0.,silence->stop_duration_str,&silence->stop_duration,'s');
+        if (!n || *n)
           return lsx_usage(effp);
 
         parse_count = sscanf(argv[1], "%lf%c", &silence->stop_threshold,
--- a/src/sox.c
+++ b/src/sox.c
@@ -674,9 +674,10 @@
     }
     break;
     case 2: if (!(effp->handler.flags & SOX_EFF_MODIFY)) {
-      lsx_fail("effects that modify audio must not follow dither");
-      exit(1);
+      lsx_warn("%s: effects that modify audio should not follow dither",
+        effp->handler.name);
     }
+    break;
   }
   return sox_add_effect(chain, effp, in, out);
 }
@@ -987,8 +988,7 @@
   int guard = is_guarded - 1;
   unsigned i;
   sox_effect_t * effp;
-  char * rate_arg = is_player ? play_rate_arg ? play_rate_arg :
-      (rate_arg = getenv("PLAY_RATE_ARG")) ? rate_arg : "-l" : NULL;
+  char * rate_arg = is_player ? (play_rate_arg ? play_rate_arg : "-l") : NULL;
 
   /* 1st `effect' in the chain is the input combiner_signal.
    * add it only if its not there from a previous run.  */
@@ -1885,11 +1885,10 @@
 "-v|--volume FACTOR       Input file volume adjustment factor (real number)",
 "--ignore-length          Ignore input file length given in header; read to EOF",
 "-t|--type FILETYPE       File type of audio",
-"-s/-u/-f/-U/-A/-i/-a/-g  Encoding type=signed-integer/unsigned-integer/floating",
-"                         point/mu-law/a-law/ima-adpcm/ms-adpcm/gsm-full-rate",
-"-e|--encoding ENCODING   Set encoding (ENCODING in above list)",
+"-e|--encoding ENCODING   Set encoding (ENCODING may be one of signed-integer,",
+"                         unsigned-integer, floating-point, mu-law, a-law,",
+"                         ima-adpcm, ms-adpcm, gsm-full-rate)",
 "-b|--bits BITS           Encoded sample size in bits",
-"-1/-2/-3/-4/-8           Encoded sample size in bytes",
 "-N|--reverse-nibbles     Encoded nibble-order",
 "-X|--reverse-bits        Encoded bit-order",
 "--endian little|big|swap Encoded byte-order; swap means opposite to default",
@@ -2382,29 +2381,33 @@
       }
       break;
 
-    case '1': f->encoding.bits_per_sample = 8;  break;
-    case '2': f->encoding.bits_per_sample = 16; break;
-    case '3': f->encoding.bits_per_sample = 24; break;
-    case '4': f->encoding.bits_per_sample = 32; break;
-    case '8': f->encoding.bits_per_sample = 64; break;
+#define DEPRECATED lsx_warn("Option `-%c' is deprecated, use `-b %i' instead.", c, (c-'0')*8)
+    case '1': f->encoding.bits_per_sample = 8;  DEPRECATED; break;
+    case '2': f->encoding.bits_per_sample = 16; DEPRECATED; break;
+    case '3': f->encoding.bits_per_sample = 24; DEPRECATED; break;
+    case '4': f->encoding.bits_per_sample = 32; DEPRECATED; break;
+    case '8': f->encoding.bits_per_sample = 64; DEPRECATED; break;
+#undef DEPRECATED
 
-    case 's': f->encoding.encoding = SOX_ENCODING_SIGN2;     break;
-    case 'u': f->encoding.encoding = SOX_ENCODING_UNSIGNED;  break;
-    case 'f': f->encoding.encoding = SOX_ENCODING_FLOAT;     break;
-    case 'a': f->encoding.encoding = SOX_ENCODING_MS_ADPCM;  break;
-    case 'i': f->encoding.encoding = SOX_ENCODING_IMA_ADPCM; break;
-    case 'o': f->encoding.encoding = SOX_ENCODING_OKI_ADPCM; break;
-    case 'g': f->encoding.encoding = SOX_ENCODING_GSM;       break;
+#define DEPRECATED(encname) lsx_warn("Option `-%c' is deprecated, use `-e %s' instead.", c, encname)
+    case 's': f->encoding.encoding = SOX_ENCODING_SIGN2;     DEPRECATED("signed-integer"); break;
+    case 'u': f->encoding.encoding = SOX_ENCODING_UNSIGNED;  DEPRECATED("unsigned-integer"); break;
+    case 'f': f->encoding.encoding = SOX_ENCODING_FLOAT;     DEPRECATED("floating-point"); break;
+    case 'a': f->encoding.encoding = SOX_ENCODING_MS_ADPCM;  DEPRECATED("ms-adpcm"); break;
+    case 'i': f->encoding.encoding = SOX_ENCODING_IMA_ADPCM; DEPRECATED("ima-adpcm"); break;
+    case 'o': f->encoding.encoding = SOX_ENCODING_OKI_ADPCM; DEPRECATED("oki-adpcm"); break;
+    case 'g': f->encoding.encoding = SOX_ENCODING_GSM;       DEPRECATED("gsm-full-rate"); break;
 
-    case 'U': f->encoding.encoding = SOX_ENCODING_ULAW;
+    case 'U': f->encoding.encoding = SOX_ENCODING_ULAW; DEPRECATED("mu-law");
       if (f->encoding.bits_per_sample == 0)
         f->encoding.bits_per_sample = 8;
       break;
 
-    case 'A': f->encoding.encoding = SOX_ENCODING_ALAW;
+    case 'A': f->encoding.encoding = SOX_ENCODING_ALAW; DEPRECATED("a-law");
       if (f->encoding.bits_per_sample == 0)
         f->encoding.bits_per_sample = 8;
       break;
+#undef DEPRECATED
 
     case 'L': case 'B': case 'x':
       if (f->encoding.reverse_bytes != sox_option_default || f->encoding.opposite_endian)
--- a/src/synth.c
+++ b/src/synth.c
@@ -287,6 +287,7 @@
   channel_t master, * chan = &master;
   int key = INT_MAX, argn = 0;
   char dummy, * end_ptr;
+  const char *n;
   --argc, ++argv;
 
   if (argc && !strcmp(*argv, "-n")) p->no_headroom = sox_true, ++argv, --argc;
@@ -304,7 +305,8 @@
     p->length_str = lsx_malloc(strlen(argv[argn]) + 1);
     strcpy(p->length_str, argv[argn]);
     /* Do a dummy parse of to see if it will fail */
-    if (lsx_parsesamples(0., p->length_str, &p->samples_to_do, 't') == NULL)
+    n = lsx_parsesamples(0., p->length_str, &p->samples_to_do, 't');
+    if (!n || *n)
       return lsx_usage(effp);
     argn++;
   }
--- a/src/tempo.c
+++ b/src/tempo.c
@@ -347,14 +347,3 @@
   handler.flags &= ~SOX_EFF_LENGTH;
   return &handler;
 }
-
-/*------------------------- key (old name for pitch) -------------------------*/
-
-sox_effect_handler_t const * lsx_key_effect_fn(void)
-{
-  static sox_effect_handler_t handler;
-  handler = *lsx_pitch_effect_fn();
-  handler.name = "key";
-  handler.flags |= SOX_EFF_DEPRECATED;
-  return &handler;
-}
--- a/src/trim.c
+++ b/src/trim.c
@@ -32,6 +32,7 @@
     char *end;
     priv_t * trim = (priv_t *) effp->priv;
     size_t samples;
+    const char *n;
   --argc, ++argv;
 
     /* Do not know sample rate yet so hold off on completely parsing
@@ -47,7 +48,8 @@
             trim->end_str = lsx_malloc(strlen(end)+1);
             strcpy(trim->end_str, end);
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., trim->end_str, &samples, 't') == NULL)
+            n = lsx_parsesamples(0., trim->end_str, &samples, 't');
+            if (!n || *n)
               return lsx_usage(effp);
             trim->length = samples;
         case 1:
@@ -54,7 +56,8 @@
             trim->start_str = lsx_malloc(strlen(argv[0])+1);
             strcpy(trim->start_str,argv[0]);
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., trim->start_str, &samples, 't') == NULL)
+            n = lsx_parsesamples(0., trim->start_str, &samples, 't');
+            if (!n || *n)
               return lsx_usage(effp);
             trim->start = samples;
             break;
--- a/test/ltest.pl
+++ b/test/ltest.pl
@@ -23,13 +23,13 @@
 
 # set default values
 my $sox='../src/sox';
-my $effect='resample';
-#my $effect='resample -qs';
-#my $effect='resample -q';
-#my $effect='resample -ql';
-#my $effect='polyphase -cutoff 0.90';
-#my $effect='filter 400-2000';
-#my $effect='filter 400-2000 1024';
+my $effect='rate';
+#my $effect='rate -q';
+#my $effect='rate -l';
+#my $effect='rate -h -M';
+#my $effect='rate -h -b 90';
+#my $effect='sinc 400-2000';
+#my $effect='sinc -n 1024 400-2000';
 
 #my ($rate0,$rate1)=(44100,44100); # sample rates
 my ($rate0,$rate1)=(8000,22050); # sample rates
@@ -60,7 +60,7 @@
 }
 
 my $ratechange=0;
-if ($effect =~ m{^(rabbit|resample|polyphase|rate)}) {
+if ($effect =~ m{^(rate|upsample|downsample|speed)}) {
   $ratechange=1;
 }