shithub: sox

Download patch

ref: 19f64639e51ac6436c0487e8382dfd778a7d6d60
parent: 7b8a31bb5c241bd5db253ed28c2a8325711e8f7f
author: cbagwell <cbagwell>
date: Thu Nov 11 15:48:01 EST 1999

Adding a lot of patches from Stan Brooks.

--- a/Changelog
+++ b/Changelog
@@ -6,6 +6,25 @@
 
 sox-12.17
 ---------
+  o Fixed a segfault problem with ulaw/alaw conversion, where
+    an out-of-range index into the tables could occur.
+  o More detailed output from the stat effect.
+  o Continued rewrite of resample.c, now it is almost as
+    fast with floating arithmetic as the old (buggy) version
+    was with 16-bit integer arithmetic.  The older version
+    in sox-12.16 shifted frequencies slightly and was less
+    accurate.
+  o New effect 'filter' which is a high-quality DSP lowpass/
+    highpass/bandpass filter using windowed sinc function
+    methods, like polyphase and resample.
+  o New data file type supported, -sl or extension .sl for
+    signed 32-bit integers.  Some simplification of the raw.c
+    source.
+  o Some test programs and scripts in the test directory, for
+    making gnuplot plots of frequency response, error-levels
+    of rate-conversion and filter effects.
+  o Removed sbdsp code.  All modern unixes are support via OSS,
+    ALSA, or sun audio device interfaces.
   o Added AVR handler from Jan Paul Schmidt.
   o SoX now waits until the last possible moment before opening
     the output file.  This will allow all input and effect options
--- /dev/null
+++ b/Copyright
@@ -1,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- a/INSTALL
+++ b/INSTALL
@@ -9,7 +9,7 @@
 Compiling
 ---------
 
-The perfered method for compiling sox is to use the "configure" scripts
+The prefered method for compiling sox is to use the "configure" scripts
 compatible with most unix systems that contain "/bin/sh" or equivalent
 (even the Win95/NT Cygwin setup will work with this).
 
@@ -37,7 +37,6 @@
     OS/2       Makefile.unx (using EMX GCC compiler)
     OS9        Makefile.os9
     UNIX       Makefile.unx (or most platforms using GCC compatible compiler)
-    VMS        descrip.mms & sox.opt (Support is outdated.  Read vms.lis)
     WIN95/NT   Makefile.unx (using Cynus GCC for Win32)
             or Makefile.dos (with a little modifying for Visual C++)
 
--- a/Makefile.ami
+++ b/Makefile.ami
@@ -18,11 +18,11 @@
 
 FSRC	= 8svx.c aiff.c alsa.c au.c auto.c avr.c cdr.c cvsd.c dat.c \
 	  g721.c g723_24.c g723_40.c g72x.c gsm.c hcom.c maud.c oss.c raw.c \
-	  sbdsp.c sf.c smp.c sndrtool.c sunaudio.c tx16w.c voc.c wav.c wve.c
+	  sf.c smp.c sndrtool.c sunaudio.c tx16w.c voc.c wav.c wve.c
 
 ESRC	= avg.c band.c chorus.c compandc copy.c cut.c deemphas.c dyn.c echo.c \
-	  echos.c flanger.c highp.c lowp.c map.c mask.c phaser.c pick.c \
-	  polyphas.c rate.c resample.c reverb.c reverse.c split.c \
+	  echos.c filter.c flanger.c highp.c lowp.c map.c mask.c phaser.c \
+	  pick.c polyphas.c rate.c resample.c reverb.c reverse.c split.c \
 	  stat.c swap.c vibro.c 
 
 PSRC= sox.c
@@ -43,19 +43,16 @@
 
 DOS	  = tests.bat testall.bat
 
-VMS       = descrip.mms sound2au.com sound2sun.c sound2sun.opt \
-	    sox.opt tests.com vms.lis
-
-FILES     = $(MISC) $(HEADERS) $(SOURCES) $(AMIGA) $(DOS) $(VMS) \
+FILES     = $(MISC) $(HEADERS) $(SOURCES) $(AMIGA) $(DOS) \
 	    $(SKEL) $(TESTS)
 
 FOBJ	= 8svx.o aiff.o alsa.o au.o auto.o avr.o cdr.o cvsd.o dat.o \
 	  g721.o g723_24.o g723_40.o g72x.o gsm.o hcom.o maud.o oss.o raw.o \
-	  sbdsp.o sf.o smp.o sndrtool.o sunaudio.o tx16w.o voc.o wav.o wve.o
+	  sf.o smp.o sndrtool.o sunaudio.o tx16w.o voc.o wav.o wve.o
 
 EOBJ	= avg.o band.o chorus.o compand.o copy.o cut.o deemphas.o dyn.o echo.o \
-	  echos.o flanger.o highp.o lowp.o map.o mask.o phaser.o pick.o \
-	  polyphas.o rate.o resample.o reverb.o reverse.o split.o \
+	  echos.o filter.o flanger.o highp.o lowp.o map.o mask.o phaser.o \
+	  pick.o polyphas.o rate.o resample.o reverb.o reverse.o split.o \
 	  stat.o swap.o vibro.o
 
 ##SOUNDLIB is defined below
--- a/Makefile.dos
+++ b/Makefile.dos
@@ -12,12 +12,12 @@
 
 FOBJ	= 8svx.obj aiff.obj alsa.obj au.obj auto.obj avr.obj cdr.obj cvsd.obj \
 	  dat.obj g721.obj g723_24.obj g723_40.obj g72x.obj gsm.obj \
-	  hcom.obj maud.obj oss.obj raw.obj sbdsp.obj sf.obj smp.obj \
+	  hcom.obj maud.obj oss.obj raw.obj sf.obj smp.obj \
 	  sndrtool.obj sunaudio.obj tx16w.obj voc.obj wav.obj wve.obj
 
 EOBJ	= avg.obj band.obj chorus.obj compand.obj copy.obj cut.obj \
-	  deemphas.obj dyn.obj echo.obj echos.obj flanger.obj highp.obj \
-          lowp.obj map.obj mask.obj phaser.obj pick.obj polyphas.obj \
+	  deemphas.obj dyn.obj echo.obj echos.obj filter.obj flanger.obj \
+          highp.obj lowp.obj map.obj mask.obj phaser.obj pick.obj polyphas.obj \
 	  rate.obj resample.obj reverb.obj reverse.obj split.obj \
 	  stat.obj swap.obj vibro.obj
 
--- a/Makefile.os9
+++ b/Makefile.os9
@@ -17,13 +17,14 @@
 	  $(RDIR)/cdr.r $(RDIR)/cvsd.r $(RDIR)/dat.r \
 	  $(RDIR)/g721.r $(RDIR)/g723_24.r $(RDIR)/g723_40.r \
 	  $(RDIR)/g72x.r $(RDIR)/gsm.r $(RDIR)/hcom.r $(RDIR)/maud.r \
-	  $(RDIR)/oss.r $(RDIR)/raw.r $(RDIR)/sbdsp.r $(RDIR)/sf.r \
+	  $(RDIR)/oss.r $(RDIR)/raw.r $(RDIR)/sf.r \
 	  $(RDIR)/smp.r $(RDIR)/sndrtool.r $(RDIR)/sunaudio.r \
 	  $(RDIR)/tx16w.r $(RDIR)/voc.r $(RDIR)/wav.r $(RDIR)/wve.r
 
 EOBJ	= $(RDIR)/avg.r $(RDIR)/band.r $(RDIR)/chorus.r \
 	  $(RDIR)/copy.r $(RDIR)/comand.r $(RDIR)/cut.r $(RDIR)/deemphas.r \
-	  $(RDIR)/dyn.r $(RDIR)/echo.r $(RDIR)/echos.r $(RDIR)/flanger.r \
+	  $(RDIR)/dyn.r $(RDIR)/echo.r $(RDIR)/echos.r $(RDIR)/filter.r \
+	  $(RDIR)/flanger.r \
 	  $(RDIR)/highp.r $(RDIR)/lowp.r $(RDIR)/map.r $(RDIR)/mask.r \
 	  $(RDIR)/phaser.r $(RDIR)/pick.r $(RDIR)/polyphas.r $(RDIR)/rate.r \
 	  $(RDIR)/resample.r $(RDIR)/reverb.r $(RDIR)/reverse.r \
--- a/Makefile.unx
+++ /dev/null
@@ -1,272 +1,0 @@
-#
-# Sound Tools Makefile
-#
-# 	builds libst.a and sox
-#
-# Updated on 02/24/97 - by Chris Bagwell (cbagwell@sprynet.com)
-#   Inhanced Makefile to install software and documented a little better.
-#
-# Updated on 05 May 1998 by Chris Bagwell (cbagwell@sprynet.com)
-#   Made some changes for various platforms based on others sugestions
-#   and made my home system (Linux) the default. ;-)
-#
-# July 19, 1998 - Chris Bagwell (cbagwell@sprynet.com)
-#   Redid makefile so that libraries could be optionally linked in.
-#   Also made each specific portion of system specifics a seperate
-#   line to comment/uncomment so that it will be easier to see how
-#   to compiler on a wider array of systems (he says with a grin).
-#   
-
-# These things are site dependant so you may want to change.
-PREFIX	= /usr/local
-BINDIR  = $(PREFIX)/bin
-LIBDIR	= $(PREFIX)/lib
-MANDIR  = $(PREFIX)/man
-INCDIR	= $(PREFIX)/include
-
-SRCDIR	= sox-12.16
-
-##############################################################################
-
-FSRC	= 8svx.c aiff.c alsa.c au.c auto.c avr.c cdr.c cvsd.c dat.c \
-	  g721.c g723_24.c g723_40.c g72x.c gsm.c hcom.c maud.c oss.c raw.c \
-	  sbdsp.c sf.c smp.c sndrtool.c sunaudio.c tx16w.c voc.c wav.c wve.c
-
-ESRC	= avg.c band.c chorus.c compand.c copy.c cut.c deemphas.c dyn.c echo.c \
-	  echos.c flanger.c highp.c lowp.c map.c mask.c phaser.c pick.c \
-	  polyphas.c rate.c resample.c reverb.c reverse.c split.c \
-	  stat.c swap.c vibro.c 
-
-PSRC	= sox.c
-
-SOURCES = $(PSRC) $(FSRC) $(ESRC) handlers.c libst.c misc.c util.c getopt.c
-
-##############################################################################
-
-HEADERS = st.h libst.h sfheader.h sfircam.h patchlvl.h version.h wav.h \
-	  g72x.h resdefs.h resampl.h
-
-TESTS   = tests.sh testall.sh monkey.au monkey.voc
-
-MISC    = README INSTALL TODO TIPS CHEAT CHEAT.eft Changelog sox.1 sox.txt \
-	  libst.3 libst.txt play.1 Makefile.unx Makefile.dos Makefile.b30 \
-	  Makefile.c70 soxeffect play rec
-
-SKEL	= skel.c skeleff.c
-
-AMIGA	= Makefile.ami amiga.h
-
-DOS	= tests.bat testall.bat
-
-OS9	= Makefile.os9
-
-VMS     = descrip.mms sound2au.com sound2sun.c sound2sun.opt \
-	  sox.opt tests.com vms.lis
-
-FILES   = $(MISC) $(HEADERS) $(SOURCES) \
-	  $(AMIGA) $(DOS) $(OS9) $(VMS) \
-	  $(SKEL) $(TESTS)
-
-##############################################################################
-
-FOBJ	= 8svx.o aiff.o alsa.o au.o auto.o avr.o cdr.o cvsd.o dat.o \
-	  g721.o g723_24.o g723_40.o g72x.o gsm.o hcom.o maud.o oss.o raw.o \
-	  sbdsp.o sf.o smp.o sndrtool.o sunaudio.o tx16w.o voc.o wav.o wve.o
-
-EOBJ	= avg.o band.o chorus.o compand.o copy.o cut.o deemphas.o dyn.o echo.o \
-	  echos.o flanger.o highp.o lowp.o map.o mask.o phaser.o pick.o \
-	  polyphas.o rate.o resample.o reverb.o reverse.o split.o \
-	  stat.o swap.o vibro.o
-
-SOUNDLIB = libst.a
-LIBOBJS = $(FOBJ) $(EOBJ) handlers.o libst.o misc.o util.o getopt.o
-
-##############################################################################
-
-#
-# System dependency parameters
-#   Find anything related to your system and uncomment.
-#
-
-# Default way to delete files.
-RM	    = rm -f
-
-# Chose the best compiler you got from the following:
-#
-# GCC with all warnings and debug info
-CC		= gcc -g -Wall
-#
-# GCC with no special options
-# CC		= gcc
-#
-# Generic compiler on your system
-# CC		= cc
-#
-# EMX GCC under OS/2 seems to need the following
-# CC		= gcc -Zcrtdll -Zexe
-
-# For optimized compilation, uncomment one of the following that your
-# compiler understands.
-#
-# gcc's all understand this as do lots of standard compilers.  Try this one
-# first.
-# O		= -O2
-
-# getopt() support is defined here.  If you have a built-in
-# getopt() that is compatible with SVR5 then you don't need to
-# do anything special.
-#
-# If you don't have any getopt() function then use the following
-# define to use Sox's builtin version
-# GETOPT_DEFINES	= -DHAVE_GETOPT
-#
-# If your system has the more advanced version of getopt() that
-# also has its own getopt.h file (Such as the case with GNU libc 2.0)
-# then uncomment the following line.  Don't uncomment anything if
-# its in stdlib.h.
-GETOPT_DEFINES	= -DHAVE_GETOPT_H
-
-# Uncomment the following if your system does not have a built in
-# strerror().  This includes SunOS.
-#
-# STRERR_DEFINES	= -DHAVE_STRERROR
-
-# Uncomment the following if your system does not have a built in
-# MEMMOVE function.  Sox will attempt to use bcopy instead.
-# SunOS has this problem.
-#
-# MEMMOVE_DEFINES	= -DHAVE_MEMMOVE
-
-# If you have the GSM 6.10 libraries installed then uncomment the follow
-# 4 lines, and change to reflect your installation paths.
-#
-# GSM_PRE_LIBS	= -L/usr/local/lib
-# GSM_POST_LIBS	= -lgsm
-# GSM_INCLUDES	= -I/usr/local/include/
-# GSM_DEFINES	= -DHAVE_LIBGSM
-
-# For sound support on machines that include the OSS sound driver
-# (such as Linux) then uncomment the following line.
-#
-# PLAYER_DEFINES = -DOSS_PLAYER
-
-# For sound support using the ALSA driver then uncomment the following line.
-#
-# PLAYER_DEFINES = -DALSA_PLAYER
-
-# For sound support under SunOS and Solaris then uncomment the following line.
-#
-# PLAYER_DEFINES = -DSUNAUDIO_PLAYER
-
-# For sound support on 386 AT&T Unix then uncomment the following line
-#
-# PLAYER_DEFINES = -DBLASTER
-
-# For sound support on Intel BSD-derived Unix's using Steve Haenichen's SBLAST
-# driver uncomment the following line.
-#
-# PLAYER_DEFINES = -DSBLAST
-
-# Uncomment the following lines if your compiling under DOS or Windows.
-# defines .snd to mean a DOS soundtool file (starts with SOUND)
-#
-# DOS_DEFINES	= -DDOS
-# RM		= del /q
-
-# Uncomment the following line if compiling under NeXT.
-# defines .snd to mean a NeXT sound format file only.
-#
-# NEXT_DEFINES	= -DNeXT
-
-# MISC DEFINES - The catch all for things that make even less sense
-#  then normal under unix.  If you need more than one of the following
-#  MISC DEFINES remember to include them on one line so it isn't just
-#  redefined.
-#
-# If your sysetem has unistd.h then you'll most like need to add 
-# HAVE_UNISTD_H to your misd defines.
-# MISC_DEFINES = -DHAVE_UNISTD_H
-#
-# If your system has malloc.h then you'll most likely need to add
-# HAVE_MALLOC_H to your misd defines.
-# MSIC_DEFINS = -DHAVE_UNISTD_H
-#
-# Testing new improved rate code.  You can use the older version if ther
-# are problems.
-# MISC_DEFINES	= -DUSE_OLD_RATE
-#
-# For an extra 32k memory, you can include u-law/a-law lookup
-# tables to speed compressiong/decompression of this type data.
-# MISC_DEFINES = -DFAST_ULAW_COMPRESSION -DFAST_ALAW_COMPRESSION 
-
-
-##############################################################################
-
-# Library setup
-
-# How should libaries be created.  Most systems can simply use the following.
-AR		= ar r
-
-# How should 'ranlib' be performed. HPUX, Linux, BSD-ish, SunOS, Solaris
-RANLIB		= ranlib
-
-# AT&T System V and GCC on DOS or OS/2 based systems
-# RANLIB	= ar ts
-
-# Some systems don't have a ranlib that you can run.  Use the following
-# for those systems.
-# RANLIB    = true
-
-# Some systems (i.e. MacOsX Server) don't need a separate math library
-MATHLIB = -lm
-# MATHLIB = 
-
-##############################################################################
-
-SOX_PRE_LIBS	= $(GSM_PRE_LIBS)
-SOX_POST_LIBS	= $(GSM_POST_LIBS) $(MATHLIB)
-SOX_INCLUDES	= $(GSM_INCLUDES)
-SOX_DEFINES	= $(GSM_DEFINES) $(PLAYER_DEFINES) \
-  $(GETOPT_DEFINES) $(STRERR_DEFINES) $(MEMMOVE_DEFINES) \
-  $(DOS_DEFINES) $(NEXT_DEFINES) $(MISC_DEFINES)
-
-CFLAGS  = $O $(SOX_DEFINES) $(SOX_INCLUDES)
-
-all: sox
-
-sox: sox.o $(SOUNDLIB)
-	$(CC) $(CFLAGS) -o sox sox.o $(SOUNDLIB) $(SOX_PRE_LIBS) $(SOX_POST_LIBS)
-
-$(SOUNDLIB): $(LIBOBJS)
-	$(RM) $(SOUNDLIB)
-	$(AR) $(SOUNDLIB) $(LIBOBJS)
-	$(RANLIB) $(SOUNDLIB)
-
-sox.o:		sox.c st.h
-
-$(LIBOBJS):	st.h version.h patchlvl.h
-
-man: sox.1 libst.3
-	$(RM) sox.txt libst.txt
-	nroff -man sox.1 | col -b > sox.txt
-	nroff -man libst.3 | col -b > libst.txt
-
-install: sox
-	if [ -f $(BINDIR)/rec ] ; then $(RM) $(BINDIR)/rec ; fi
-	if [ -f $(MANDIR)/man1/rec.1 ] ; then $(RM) $(MANDIR)/man1/rec.1 ; fi
-	install -c -m 755 sox play $(BINDIR)
-	install -c -m 644 sox.1 play.1 $(MANDIR)/man1
-	ln -s $(BINDIR)/play $(BINDIR)/rec
-	ln -s $(MANDIR)/man1/play.1 $(MANDIR)/man1/rec.1
-
-install-lib: libst.a
-	install -c -m 644 libst.a $(LIBDIR)
-	install -c -m 644 libst.3 $(MANDIR)/man3
-	install -c -m 644 st.h $(INCDIR)
-
-clean:
-	$(RM) *~ *.o *.raw *.sf core sox libst.a
-
-tar:	clean
-	$(RM) ../$(SRCDIR).tar
-	cd ..; tar cvf $(SRCDIR).tar $(SRCDIR)
--- a/README
+++ b/README
@@ -59,7 +59,7 @@
 
 History:
 
-This is the 12th release, Patchlevel 16 of the Sound Tools.
+This is the 12th release, Patchlevel 17 of the Sound Tools.
 SoX was originally written and maintained by Lance Norskog but
 unfortunetly he has stopped maintaining it since 1995.  I, Chris
 Bagwell (cbagwell@sprynet.com), have started maintaining it since
@@ -96,9 +96,9 @@
 tools for computer multimedia work, similar to the PBM toolkit for 
 image manipulation.
 
-Sound Tools may be used for any purpose.  Source
-distributions must include the copyright notices.  Binary
-distributions must include acknowledgements to the creators.
+Sound Tools may be used for any purpose.  Source distributions must
+must include the copyright notices, and (lack of) warranty information.
+Binary distributions must include acknowledgements to the creators.
 Files are copyright by their respective authors.
 
 If you have bug fixes/enhancements, please send it to me as I would like
@@ -180,6 +180,9 @@
 			Libst porting bugs
 		Lauren Weinstein	lauren@vortex.com
 			DOS porting, scripts, professional use
+		Stan Brooks		stabro@megsinet.net
+			Rewrite of resample and polyphase code.
+			DSP filter effect.  Some test code/scripts.
 		Chris Bagwell		cbagwell@sprynet.com
 			OSS and Sun players, bugfixes, ADPCM support,
 			patch collection and maintance.
--- a/configure.in
+++ b/configure.in
@@ -59,15 +59,6 @@
 		CFLAGS="$CFLAGS -D_ALL_SOURCE"
 		;;
 
-	*att* )
-		dnl 386 AT&T Unix.
-		CFLAGS="$CFLAGS -DBLASTER"
-		;;
-
-	i*86-*-bsd* )
-		CFLAGS="$CFLAGS -DSBLAST"
-		;;
-
 	*hpux* )
 		CFLAGS="$CFLAGS -D_HPUX_SOURCE"
 		;;
--- a/descrip.mms
+++ /dev/null
@@ -1,284 +1,0 @@
-#
-# MMS description file for SOX/SoundTools (and Gopstein/Harris sound2sun)
-#
-# Modification History
-# 12 Dec 1992, K. S. Kubo, Created
-#
-# NOTES (todo):
-#	* This does not yet provide support for VMS distribution (e.g. shar
-#	  target).
-#	* It may be nice to link the library as a shareable image.
-#	* To do this "right" this should also provide support for sounds
-#	  in the DDIF format... someday, maybe.
-#
-# !!!!!!!! IMPORTANT !!!!!!!!!! This file is outdated.  Please refer
-# to Makefile.unx to see which source files need to be compiled
-# and update accordingly.  Please send any updates to cbagwell@sprynet.com
-
-.IFDEF DEBUG
-DEBUGFLAGS	= /debug/nooptimize
-LINKDBGFLAGS	= /nouserlibrary/traceback/debug
-.ELSE
-DEBUGFLAGS	= /nodebug/optimize
-LINKDBGFLAGS	= /nouserlibrary/notraceback/nodebug
-.ENDIF
-
-CC		= cc
-CFLAGS		= /object=$*.OBJ$(DEBUGFLAGS)
-LINK		= link
-LINKFLAGS	= /executable=$*.EXE$(LINKDBGFLAGS)
-
-
-FSRC	= 	raw.c, \
-	  	voc.c, \
-		au.c, \
-		sf.c, \
-	  	aiff.c, \
-		hcom.c, \
-		8svx.c, \
-		sndrtool.c, \
-		wav.c, \
-		sbdsp.c, \
-		sunaduo.c, \
-		oss.c, \
-		smp.c, \
-		auto.c
-
-ESRC	=	copy.c, \
-		avg.c, \
-		stat.c, \
-		vibro.c, \
-		echo.c, \
-		rate.c, \
-		band.c, \
-		lowp.c, \
-		highp.c, \
-		reverse.c, \
-		dyn.c, \
-		cut.c, \
-		map.c, \
-		split.c, \
-		pick.c, \
-		mask.c, \
-		resample.c
-
-PSRC	=	sox.c
-
-OSRC	=	sound2sun.c
-
-SOURCES = 	$(FSRC),$(ESRC),$(PSRC), \
-		handlers.c, libst.c, misc.c, getopt.c, \
-		$(OSRC)
-
-HDRS	=	st.h, \
-		libst.h, \
-		sfheader.h, \
-		sfircam.h, \
-		patchlevel.h, \
-		version.h, \
-		wav.h, \
-		g72x.h,\
-		resdefs.h, \
-		resampl.h
-
-TESTS	=	tests.sh, \
-		testall.sh, \
-		monkey.au, \
-		monkey.voc
-
-MISC    = 	readme., readme2., install., todo, tips, cheat, sox.1, \
-		sox.txt, libst.3, libst.txt, makefile.unx, makefile.bor, \
-		Makefile.b30, Makefile.c70, soxeffect, play, rec
-
-VMS	=	descrip.mms, sox.opt, vms.lis, sound2au.com, sound2sun.opt, \
-		sound2sun.c, tests.com
-
-SKEL	  = skel.c skeleff.c
-
-SOUNDLIB  =	soundtools.olb
-
-LIBMODS	= \
-    $(SOUNDLIB)(raw) \
-    $(SOUNDLIB)(voc) \
-    $(SOUNDLIB)(au) \
-    $(SOUNDLIB)(sf) \
-    $(SOUNDLIB)(aiff) \
-    $(SOUNDLIB)(hcom) \
-    $(SOUNDLIB)(8svx) \
-    $(SOUNDLIB)(sndrtool) \
-    $(SOUNDLIB)(wav) \
-    $(SOUNDLIB)(sbdsp) \
-    $(SOUNDLIB)(sunaudio) \
-    $(SOUNDLIB)(oss) \
-    $(SOUNDLIB)(smp) \
-    $(SOUNDLIB)(auto) \
-    $(SOUNDLIB)(copy) \
-    $(SOUNDLIB)(avg) \
-    $(SOUNDLIB)(stat) \
-    $(SOUNDLIB)(vibro) \
-    $(SOUNDLIB)(echo) \
-    $(SOUNDLIB)(rate) \
-    $(SOUNDLIB)(band) \
-    $(SOUNDLIB)(lowp) \
-    $(SOUNDLIB)(reverse) \
-    $(SOUNDLIB)(handlers) \
-    $(SOUNDLIB)(libst) \
-    $(SOUNDLIB)(misc) \
-    $(SOUNDLIB)(getopt)
-
-.FIRST
-    @ if F$TrnLnm("VAXC$INCLUDE") .eqs. "" then define VAXC$INCLUDE sys$library
-    @ if F$TrnLnm("SYS") .eqs. "" then define SYS sys$library
-
-#
-# Actual targets
-#
-all : sox.exe sound2sun.exe
-    @ ! dummy argument
-
-clean :
-    - delete *.obj;
-    - delete *.raw;
-    - delete *.sf;
-
-depend : $(HDRS) $(SOURCES)
-    set command/replace clddir:depend
-    depend $(SOURCES)
-    ! dependencies updated
-
-sox.exe : sox.obj $(SOUNDLIB) descrip.mms sox.opt
-    $(LINK) $(LINKFLAGS) sox.obj, sox.opt/options
-
-sound2sun.exe : sound2sun.obj descrip.mms sound2sun.opt
-    $(LINK) $(LINKFLAGS) sound2sun.obj, sound2sun.opt/options
-
-$(SOUNDLIB) : $(LIBMODS)
-    ! $(SOUNDLIB) updated
-
-#DO NOT DELETE THIS LINE!
-
-raw.obj : libst.h
-raw.obj : raw.c
-raw.obj : st.h
-raw.obj : sys$library:stddef.h
-raw.obj : sys$library:stdio.h
-voc.obj : st.h
-voc.obj : voc.c
-voc.obj : sys$library:stddef.h
-voc.obj : sys$library:stdio.h
-au.obj : au.c
-au.obj : st.h
-au.obj : sys$library:stddef.h
-au.obj : sys$library:stdio.h
-sf.obj : sf.c
-sf.obj : sfheader.h
-sf.obj : st.h
-sf.obj : sys$library:stddef.h
-sf.obj : sys$library:stdio.h
-aiff.obj : aiff.c
-aiff.obj : st.h
-aiff.obj : sys$library:math.h
-aiff.obj : sys$library:stddef.h
-aiff.obj : sys$library:stdio.h
-hcom.obj : hcom.c
-hcom.obj : st.h
-hcom.obj : sys$library:stddef.h
-hcom.obj : sys$library:stdio.h
-8svx.obj : 8svx.c
-8svx.obj : st.h
-8svx.obj : sys$library:errno.h
-8svx.obj : sys$library:math.h
-8svx.obj : sys$library:perror.h
-8svx.obj : sys$library:stddef.h
-8svx.obj : sys$library:stdio.h
-8svx.obj : sys:types.h
-sndrtool.obj : sndrtool.c
-sndrtool.obj : st.h
-sndrtool.obj : sys$library:errno.h
-sndrtool.obj : sys$library:math.h
-sndrtool.obj : sys$library:perror.h
-sndrtool.obj : sys$library:stddef.h
-sndrtool.obj : sys$library:stdio.h
-wav.obj : st.h
-wav.obj : wav.c
-wav.obj : sys$library:stddef.h
-wav.obj : sys$library:stdio.h
-sbdsp.obj : sbdsp.c
-smp.obj : st.h
-smp.obj : smp.c
-smp.obj : sys$library:stddef.h
-smp.obj : sys$library:stdio.h
-smp.obj : sys$library:string.h
-auto.obj : st.h
-auto.obj : wav.c
-auto.obj : sys$library:stddef.h
-auto.obj : sys$library:stdio.h
-copy.obj : copy.c
-copy.obj : st.h
-copy.obj : sys$library:stddef.h
-copy.obj : sys$library:stdio.h
-avg.obj : avg.c
-avg.obj : st.h
-avg.obj : sys$library:stddef.h
-avg.obj : sys$library:stdio.h
-stat.obj : st.h
-stat.obj : stat.c
-stat.obj : sys$library:stddef.h
-stat.obj : sys$library:stdio.h
-vibro.obj : st.h
-vibro.obj : vibro.c
-vibro.obj : sys$library:math.h
-vibro.obj : sys$library:stddef.h
-vibro.obj : sys$library:stdio.h
-echo.obj : echo.c
-echo.obj : st.h
-echo.obj : sys$library:math.h
-echo.obj : sys$library:stddef.h
-echo.obj : sys$library:stdio.h
-rate.obj : rate.c
-rate.obj : st.h
-rate.obj : sys$library:math.h
-rate.obj : sys$library:stddef.h
-rate.obj : sys$library:stdio.h
-band.obj : band.c
-band.obj : st.h
-band.obj : sys$library:math.h
-band.obj : sys$library:stddef.h
-band.obj : sys$library:stdio.h
-lowp.obj : lowp.c
-lowp.obj : st.h
-lowp.obj : sys$library:math.h
-lowp.obj : sys$library:stddef.h
-lowp.obj : sys$library:stdio.h
-reverse.obj : reverse.c
-reverse.obj : st.h
-reverse.obj : sys$library:math.h
-reverse.obj : sys$library:stddef.h
-reverse.obj : sys$library:stdio.h
-sox.obj : sox.c
-sox.obj : st.h
-sox.obj : sys$library:errno.h
-sox.obj : sys$library:ctype.h
-sox.obj : sys$library:perror.h
-sox.obj : sys$library:stat.h
-sox.obj : sys$library:stddef.h
-sox.obj : sys$library:stdio.h
-sox.obj : sys$library:string.h
-sox.obj : sys$library:varargs.h
-sox.obj : sys:types.h
-handlers.obj : handlers.c
-handlers.obj : st.h
-handlers.obj : sys$library:stddef.h
-handlers.obj : sys$library:stdio.h
-libst.obj : libst.c
-misc.obj : misc.c
-misc.obj : st.h
-misc.obj : sys$library:stddef.h
-misc.obj : sys$library:stdio.h
-getopt.obj : getopt.c
-getopt.obj : st.h
-getopt.obj : sys$library:stddef.h
-getopt.obj : sys$library:stdio.h
-sound2sun.obj : sound2sun.c
-sound2sun.obj : sys$library:stddef.h
-sound2sun.obj : sys$library:stdio.h
--- a/libst.c
+++ b/libst.c
@@ -33,9 +33,10 @@
 
 unsigned char
 st_linear_to_ulaw( sample )
-int sample;
+short sample;
     {
-    static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+    static const int exp_lut[256] = 
+			      {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
                                4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
                                5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
                                5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
@@ -2208,7 +2209,7 @@
 
 unsigned char
 st_linear_to_Alaw( sample )
-int sample;
+short sample;
     {
     static int exp_lut[128] = {1,1,2,2,3,3,3,3,
                                4,4,4,4,4,4,4,4,
--- a/libst.h
+++ b/libst.h
@@ -16,9 +16,9 @@
 extern int ulaw_exp_table[256];
 extern unsigned char ulaw_comp_table[16384];
 #define st_ulaw_to_linear(ulawbyte) ulaw_exp_table[ulawbyte]
-#define st_linear_to_ulaw(linearword) ulaw_comp_table[(linearword / 4) & 0x3fff]
+#define st_linear_to_ulaw(linearword) ulaw_comp_table[((short)linearword / 4) & 0x3fff]
 #else
-unsigned char st_linear_to_ulaw( /* int sample */ );
+unsigned char st_linear_to_ulaw( /* short sample */ );
 int st_ulaw_to_linear( /* unsigned char ulawbyte */ );
 #endif
 
@@ -26,8 +26,8 @@
 extern int Alaw_exp_table[256];
 extern unsigned char Alaw_comp_table[16384];
 #define st_Alaw_to_linear(Alawbyte) Alaw_exp_table[Alawbyte]
-#define st_linear_to_Alaw(linearword) Alaw_comp_table[(linearword / 4) & 0x3fff]
+#define st_linear_to_Alaw(linearword) Alaw_comp_table[((short)linearword / 4) & 0x3fff]
 #else
-unsigned char st_linear_to_Alaw( /* int sample */ );
+unsigned char st_linear_to_Alaw( /* short sample */ );
 int st_Alaw_to_linear( /* unsigned char ulawbyte */ );
 #endif
--- a/libst.txt
+++ b/libst.txt
@@ -1,213 +1,212 @@
 
 
 
-ST(3)							    ST(3)
+C Library Functions					    ST(3)
 
 
+
 NAME
-       libst  -	 Sound	Tools  :  sound	 sample	 file and effects
-       libraries.
+     libst  -  Sound  Tools  :	sound  sample  file  and  effects
+     libraries.
 
 SYNOPSIS
-       cc file.c -o file libst.a
+     cc	file.c -o file libst.a
 
 DESCRIPTION
-       Sound Tools is a library of sound sample file format read-
-       ers/writers and sound effects processors.
+     Sound Tools  is  a	 library  of  sound  sample  file  format
+     readers/writers and sound effects processors.
 
-       Sound  Tools  includes  skeleton	 C files to assist you in
-       writing	new  formats  and  effects.   The  full	 skeleton
-       driver,	skel.c,	 helps you write drivers for a new format
-       which has data structures.  The	simple	skeleton  drivers
-       help  you write a new driver for raw (headerless) formats,
-       or for formats which just have a simple header followed by
-       raw data.
+     Sound Tools includes skeleton C files to assist you in writ-
+     ing  new  formats	and  effects.  The  full skeleton driver,
+     skel.c, helps you write drivers for a new format  which  has
+     data  structures. The simple skeleton drivers help	you write
+     a new driver for raw (headerless) formats,	 or  for  formats
+     which just	have a simple header followed by raw data.
 
-       Most sound sample formats are fairly simple: they are just
-       a string of bytes or words and are presumed to be  sampled
-       at  a  known  data  rate.   Most of them have a short data
-       structure at the beginning of the file.
+     Most sound	sample formats are fairly simple: they are just	a
+     string of bytes or	words and are presumed to be sampled at	a
+     known data	rate.  Most of them have a short  data	structure
+     at	the beginning of the file.
 
 INTERNALS
-       The Sound Tools formats and effects operate on an internal
-       buffer format of signed 32-bit longs.  The data processing
-       routines are called with buffers	 of  these  samples,  and
-       buffer  sizes  which  refer  to the number of samples pro-
-       cessed, not the number of bytes.	 File  readers	translate
-       the input samples to signed longs and return the number of
-       longs read.  For example, data in linear signed byte  for-
-       mat is left-shifted 24 bits.
+     The Sound Tools formats and effects operate on  an	 internal
+     buffer  format  of	signed 32-bit longs.  The data processing
+     routines are called  with	buffers	 of  these  samples,  and
+     buffer sizes which	refer to the number of samples processed,
+     not the number of bytes.  File readers translate  the  input
+     samples to	signed longs and return	the number of longs read.
+     For example, data in linear  signed  byte	format	is  left-
+     shifted 24	bits.
 
-       This  does  cause  problems  in	processing the data.  For
-       example:
-	    *obuf++ = (*ibuf++ + *ibuf++)/2;
-       would not mix down left and right channels into one  mono-
-       phonic  channel, because the resulting samples would over-
-       flow 32 bits.  Instead, the ``avg'' effects must use:
-	    *obuf++ = *ibuf++/2 + *ibuf++/2;
+     This does cause problems in processing the	data.  For  exam-
+     ple:
+	  *obuf++ = (*ibuf++ + *ibuf++)/2;
+     would not mix down	left and right channels	 into  one  mono-
+     phonic channel, because the resulting samples would overflow
+     32	bits.  Instead,	the ``avg'' effects must use:
+	  *obuf++ = *ibuf++/2 +	*ibuf++/2;
 
-       Stereo data is stored with the left and right speaker data
-       in  successive  samples.	  Quadraphonic	data is stored in
-       this order: left front,	right  front,  left  rear,  right
-       rear.
+     Stereo data is stored with	the left and right  speaker  data
+     in	 successive samples.  Quadraphonic data	is stored in this
+     order: left front,	right front, left rear,	right rear.
 
 FORMATS
-       A format is responsible for translating between sound sam-
-       ple files and an internal buffer.  The internal buffer  is
-       store  in  signed  longs	 with a fixed sampling rate.  The
-       format operates from two data structures: a format  struc-
-       ture, and a private structure.
+     A format is responsible for translating between sound sample
+     files  and	an internal buffer.  The internal buffer is store
+     in	signed longs with a  fixed  sampling  rate.   The  format
+     operates  from two	data structures:  a format structure, and
+     a private structure.
 
 
 
 
-			 October 15 1996			1
+SunOS 5.6	  Last change: October 15 1996			1
 
 
 
 
 
-ST(3)							    ST(3)
 
+C Library Functions					    ST(3)
 
-       The format structure contains a list of control parameters
-       for the sample: sampling rate, data  size  (bytes,  words,
-       floats, etc.), style (unsigned, signed, logarithmic), num-
-       ber of sound  channels.	 It  also  contains  other  state
-       information:  whether  the  sample  file needs to be byte-
-       swapped, whether fseek() will work, its suffix,	its  file
-       stream pointer, its format pointer, and the private struc-
-       ture for the format .
 
-       The private area is just a preallocated data array for the
-       format to use however it wishes.	 It should have a defined
-       data structure and cast the array to that structure.   See
-       voc.c  for  the	use of a private data area.  Voc.c has to
-       track the number of samples it writes and when  finishing,
-       seek  back  to the beginning of the file and write it out.
-       The private area is not very large.  The	 ``echo''  effect
-       has  to	malloc()  a  much  larger area for its delay line
-       buffers.
 
-       A format has 6 routines:
+     The format	structure contains a list of  control  parameters
+     for  the  sample:	sampling  rate,	 data size (bytes, words,
+     floats, etc.), style (unsigned, signed, logarithmic), number
+     of	 sound	channels.   It also contains other state informa-
+     tion: whether the sample  file  needs  to	be  byte-swapped,
+     whether  fseek()  will  work,  its	 suffix,  its file stream
+     pointer, its format pointer, and the private  structure  for
+     the format	.
 
-       startread	   Set up the format parameters, or  read
-			   in  a data header, or do what needs to
-			   be done.
+     The private area is just a	preallocated data array	 for  the
+     format  to	 use  however it wishes. It should have	a defined
+     data structure and	cast the array	to  that  structure.  See
+     voc.c for the use of a private data area. Voc.c has to track
+     the number	of samples it writes  and  when	 finishing,  seek
+     back  to  the  beginning  of the file and write it	out.  The
+     private area is not very large.  The ``echo'' effect has  to
+     malloc() a	much larger area for its delay line buffers.
 
-       read		   Given a buffer and a length:	 read  up
-			   to  that  many samples, transform them
-			   into signed long  integers,	and  copy
-			   them into the buffer.  Return the num-
-			   ber of samples actually read.
+     A format has 6 routines:
 
-       stopread		   Do what needs to be done.
+     startread		 Set up	the format parameters, or read in
+			 a  data  header,  or do what needs to be
+			 done.
 
-       startwrite	   Set up the format parameters, or write
-			   out a data header, or do what needs to
-			   be done.
+     read		 Given a buffer	and a length: read up  to
+			 that  many  samples, transform	them into
+			 signed	long integers, and copy	them into
+			 the  buffer.	Return the number of sam-
+			 ples actually read.
 
-       write		   Given a buffer and a length: copy that
-			   many	 samples  out of the buffer, con-
-			   vert them from  signed  longs  to  the
-			   appropriate	data,  and  write them to
-			   the file.  If it can't write	 out  all
-			   the samples, fail.
+     stopread		 Do what needs to be done.
 
-       stopwrite	   Fix	up  any	 file  header, or do what
-			   needs to be done.
+     startwrite		 Set up	the format parameters,	or  write
+			 out  a	 data header, or do what needs to
+			 be done.
 
+     write		 Given a buffer	and a length:  copy  that
+			 many  samples out of the buffer, convert
+			 them from signed longs	to the	appropri-
+			 ate  data,  and  write	them to	the file.
+			 If it can't write out all  the	 samples,
+			 fail.
+
+     stopwrite		 Fix up	any file header, or do what needs
+			 to be done.
+
 EFFECTS
-       An effects loop has one input and one output  stream.   It
-       has 5 routines.
+     An	effects	loop has one input and one output stream.  It has
+     5 routines.
 
-       getopts		   is  called  with  a	character  string
-			   argument list for the effect.
+     getopts		 is called with	a character string  argu-
+			 ment list for the effect.
 
 
 
+SunOS 5.6	  Last change: October 15 1996			2
 
-			 October 15 1996			2
 
 
 
 
 
-ST(3)							    ST(3)
+C Library Functions					    ST(3)
 
 
-       start		   is called with the  signal  parameters
-			   for the input and output streams.
 
-       flow		   is  called  with input and output data
-			   buffers, and (by reference) the  input
-			   and	output	data sizes.  It processes
-			   the	input  buffer  into  the   output
-			   buffer, and sets the size variables to
-			   the numbers of samples  actually  pro-
-			   cessed.   It is under no obligation to
-			   fill the output buffer.
+     start		 is called with	the signal parameters for
+			 the input and output streams.
 
-       drain		   is called  after  there  are	 no  more
-			   input  data	samples.   If  the effect
-			   wishes to generate more  data  samples
-			   it  copies  the  generated data into a
-			   given buffer and returns the number of
-			   samples  generated.	 If  it fills the
-			   buffer, it will be called again,  etc.
-			   The	echo  effect  uses  this  to fade
-			   away.
+     flow		 is called with	 input	and  output  data
+			 buffers,  and	(by  reference)	the input
+			 and output data sizes.	 It processes the
+			 input buffer into the output buffer, and
+			 sets the size variables to  the  numbers
+			 of  samples  actually	processed.  It is
+			 under no obligation to	fill  the  output
+			 buffer.
 
-       stop		   is called when there are no more input
-			   samples to process.	stop may generate
-			   output samples on its own.  See echo.c
-			   for	how to do this, and see that what
-			   it does is absolutely bogus.
+     drain		 is called after there are no more  input
+			 data  samples.	  If the effect	wishes to
+			 generate more data samples it copies the
+			 generated  data  into a given buffer and
+			 returns the number of samples generated.
+			 If  it	 fills	the  buffer,  it  will be
+			 called	again, etc.  The echo effect uses
+			 this to fade away.
 
+     stop		 is called when	there are no  more  input
+			 samples  to  process.	stop may generate
+			 output	samples	on its own.   See  echo.c
+			 for how to do this, and see that what it
+			 does is absolutely bogus.
+
 COMMENTS
-       Theoretically, formats can be used to  manipulate  several
-       files inside one program.  Multi-sample files, for example
-       the download for	 a  sampling  keyboard,	 can  be  handled
-       cleanly with this feature.
+     Theoretically, formats can	be  used  to  manipulate  several
+     files  inside  one	program.  Multi-sample files, for example
+     the download for a	sampling keyboard, can be handled cleanly
+     with this feature.
 
 PORTABILITY PROBLEMS
-       Many  computers	don't  supply  arithmetic shifting, so do
-       multiplies and divides instead of << and >>.  The compiler
-       will  do	 the  right  thing if the CPU supplies arithmetic
-       shifting.
+     Many computers don't supply arithmetic shifting, so do  mul-
+     tiplies and divides instead of << and >>.	The compiler will
+     do	the right thing	if the CPU supplies arithmetic shifting.
 
-       Do all arithmetic conversions one stage at a  time.   I've
-       had too many problems with "obviously clean" combinations.
+     Do	all arithmetic conversions one stage at	a time.	 I've had
+     too many problems with "obviously clean" combinations.
 
-       In general, don't worry	about  "efficiency".   The  sox.c
-       base translator is disk-bound on any machine (other than a
-       8088 PC with an SMD disk controller).  Just  comment  your
-       code  and  make	sure  it's clean and simple.  You'll find
-       that DSP code is extremely painful to write as it is.
+     In	general, don't worry about "efficiency". The  sox.c  base
+     translator	 is  disk-bound	on any machine (other than a 8088
+     PC	with an	SMD disk controller). Just comment your	code  and
+     make  sure	it's clean and simple.	You'll find that DSP code
+     is	extremely painful to write as it is.
 
 BUGS
-       The HCOM format is not re-entrant; it  can  only	 be  used
-       once in a program.
+     The HCOM format is	not re-entrant;	it can only be used  once
+     in	a program.
 
-       The program/library interface is pretty weak.  There's too
 
 
 
-			 October 15 1996			3
 
+SunOS 5.6	  Last change: October 15 1996			3
 
 
 
 
-ST(3)							    ST(3)
 
 
-       much ad-hoc information which a	program	 is  supposed  to
-       gather  up.   Sound  Tools  wants to be an object-oriented
-       dataflow architecture.
+C Library Functions					    ST(3)
 
 
 
+     The program/library interface is pretty weak.   There's  too
+     much  ad-hoc  information	which  a  program  is supposed to
+     gather up.	 Sound	Tools  wants  to  be  an  object-oriented
+     dataflow architecture.
 
 
 
@@ -259,6 +258,7 @@
 
 
 
-			 October 15 1996			4
+SunOS 5.6	  Last change: October 15 1996			4
+
 
 
--- a/sbdsp.c
+++ /dev/null
@@ -1,167 +1,0 @@
-
-char ansi_c_is_very_stupid_and_needs_a_variable_here;
-
-#if	defined(BLASTER) || defined(SBLAST)
-/*
- * Copyright 1992 Rick Richardson
- * Copyright 1991 Lance Norskog And Sundry Contributors
- * This source code is freely redistributable and may be used for
- * any purpose.  This copyright notice must be maintained. 
- * Rick Richardson, Lance Norskog And Sundry Contributors are not
- * responsible for the consequences of using this software.
- */
-
-/*
- * Direct to Sound Blaster device driver.
- * SBLAST patches by John T. Kohl.
- */
-
-#include <sys/types.h>
-#ifdef SBLAST
-#include <i386/isa/sblast.h>
-#else
-#include <sys/sb.h>
-#endif
-#include <signal.h>
-#include "st.h"
-
-/* Private data for SKEL file */
-typedef struct sbdspstuff {
-	int	samples;		/* bytes remaining in current block */
-} *sbdsp_t;
-
-static got_int = 0;
-
-static void
-sigint(s)
-int s;
-{
-	if (s) got_int = 1;
-	else signal(SIGINT, sigint);
-}
-
-/*
- * Do anything required before you start reading samples.
- * Read file header. 
- *	Find out sampling rate, 
- *	size and style of samples, 
- *	mono/stereo/quad.
- */
-sbdspstartread(ft) 
-ft_t ft;
-{
-	sbdsp_t sbdsp = (sbdsp_t) ft->priv;
-#ifdef	SBLAST
-	int off = 0;
-#endif
-
-	/* The following is needed to init block reads */
-	rawstartread(ft);
-
-	/* If you need to seek around the input file. */
-	if (0 && ! ft->seekable)
-		fail("SKEL input file must be a file, not a pipe");
-
-	if (!ft->info.rate)
-		ft->info.rate = 11000;
-	ft->info.size = BYTE;
-	ft->info.style = UNSIGNED;
-	ft->info.channels = 1;
-	ioctl(fileno(ft->fp), DSP_IOCTL_RESET, 0);
-#ifdef SBLAST
-	ioctl(fileno(ft->fp), DSP_IOCTL_VOICE, &off);
-	ioctl(fileno(ft->fp), DSP_IOCTL_SPEED, &ft->info.rate);
-#else
-	ioctl(fileno(ft->fp), DSP_IOCTL_VOICE, 0);
-	ioctl(fileno(ft->fp), DSP_IOCTL_SPEED, ft->info.rate);
-#endif
-	sigint(0);	/* Prepare to catch SIGINT */
-}
-
-/*
- * Read up to len samples from file.
- * Convert to signed longs.
- * Place in buf[].
- * Return number of samples read.
- */
-
-sbdspread(ft, buf, len) 
-ft_t ft;
-LONG *buf, len;
-{
-	sbdsp_t sbdsp = (sbdsp_t) ft->priv;
-	int		rc;
-
-	if (got_int) return (0);
-	rc = rawread(ft, buf, len);
-	if (rc < 0) return 0;
-	return (rc);
-}
-
-/*
- * Do anything required when you stop reading samples.  
- * Don't close input file! 
- */
-sbdspstopread(ft) 
-ft_t ft;
-{
-	rawstopread(ft);
-
-#ifdef SBLAST
-	ioctl(fileno(ft->fp), DSP_IOCTL_FLUSH, 0);
-#endif
-}
-
-sbdspstartwrite(ft) 
-ft_t ft;
-{
-	sbdsp_t sbdsp = (sbdsp_t) ft->priv;
-#ifdef	SBLAST
-	int on = 1;
-#endif
-
-	rawstartwrite(ft);
-
-	/* If you have to seek around the output file */
-	if (0 && ! ft->seekable)
-		fail("Output .sbdsp file must be a file, not a pipe");
-
-	if (!ft->info.rate)
-		ft->info.rate = 11000;
-	ft->info.size = BYTE;
-	ft->info.style = UNSIGNED;
-	ft->info.channels = 1;
-	ioctl(fileno(ft->fp), DSP_IOCTL_RESET, 0);
-#ifdef SBLAST
-	ioctl(fileno(ft->fp), DSP_IOCTL_FLUSH, 0);
-	ioctl(fileno(ft->fp), DSP_IOCTL_VOICE, &on);
-	ioctl(fileno(ft->fp), DSP_IOCTL_SPEED, &ft->info.rate);
-#else
-	ioctl(fileno(ft->fp), DSP_IOCTL_VOICE, 1);
-	ioctl(fileno(ft->fp), DSP_IOCTL_SPEED, ft->info.rate);
-#endif
-}
-
-sbdspwrite(ft, buf, len) 
-ft_t ft;
-LONG *buf, len;
-{
-	sbdsp_t sbdsp = (sbdsp_t) ft->priv;
-
-	if (len == 0) return 0;
-	return (rawwrite(ft, buf, len));
-}
-
-sbdspstopwrite(ft) 
-ft_t ft;
-{
-	/* This is needed to flush out block writes */
-	rawstopwrite(ft);
-
-	/* All samples are already written out. */
-	/* If file header needs fixing up, for example it needs the */
- 	/* the number of samples in a field, seek back and write them here. */
-	fflush(ft->fp);
-	ioctl(fileno(ft->fp), DSP_IOCTL_FLUSH, 0);
-}
-#endif
--- a/sound2au.com
+++ /dev/null
@@ -1,52 +1,0 @@
-$   FVER = 'F$Verify(0)'
-$ !
-$ ! Sound2Au.Com
-$ ! translate a variety of sound formats into Sun .au format (compatible with
-$ ! DECsound) via SOX and SOUND2SUN.
-$ !
-$ ! sound2sun was written by Rich Gopstein and Harris Corporation.
-$ !
-$ ! SOX is part of the Sound Tools package written and distributed by
-$ ! 	Lance Norskog, et. al.
-$ !
-$ ! Usage
-$ !	@sound2au file_name [frequency]
-$ !
-$ ! where:
-$ !	file_name = filename template (may contain wildcards)
-$ !	frequency = sampling frequency (default 11000 Hz)
-$ !
-$ ! Modification History
-$ !	14 Dec 1992, K. S. Kubo, Created
-$ !
-$   If P1 .Eqs. "" THEN GOTO USAGE_EXIT
-$ !
-$   FTMPL 	= F$Parse(P1,"*.SND;")
-$   If F$TrnLnm("SOX_DIR") .Nes. "" Then Goto MORE_DEFS
-$   SDIR = F$Element(0, "]", F$Environment("PROCEDURE")) + "]"
-$   Define/NoLog SOX_DIR 'SDIR'
-$ MORE_DEFS:
-$   SOX   	= "$ SOX_DIR:SOX"
-$   SOUND2SUN	= "$ SOX_DIR:SOUND2SUN"
-$   ONAME	= ""
-$   If P2 .Nes. "" Then SOUND2SUN = SOUND2SUN + " -f ''P2'"
-$ LOOP:
-$   FNAME = F$Search(FTMPL)
-$   If FNAME .Eqs. "" Then Goto REAL_EXIT
-$   If FNAME .Eqs. ONAME Then Goto REAL_EXIT
-$   ONAME = FNAME
-$   VER   = F$Parse(FNAME,,,"VERSION")
-$   FTYPE = F$Parse(FNAME,,,"TYPE")
-$   FNAME = FNAME - VER - ";"	! strip version number off
-$   BNAME = FNAME - FTYPE	! get the base name
-$   SOX 'FNAME' -t .raw -u -b 'BNAME'.raw
-$   SOUND2SUN 'BNAME'.raw 'BNAME'.au
-$   Delete/NoLog 'BNAME'.raw;
-$   Goto LOOP
-$ !
-$ USAGE_EXIT:
-$   Write Sys$Output "Usage:  @SOUND2AU file_name"
-$ !
-$ REAL_EXIT:
-$   FVER = F$Verify('FVER')
-$   EXIT 
--- a/sound2sun.c
+++ /dev/null
@@ -1,201 +1,0 @@
-/************************************************************************/
-/*      Copyright 1989 by Rich Gopstein and Harris Corporation          */
-/*                                                                      */
-/*      Permission to use, copy, modify, and distribute this software   */
-/*      and its documentation for any purpose and without fee is        */
-/*      hereby granted, provided that the above copyright notice        */
-/*      appears in all copies and that both that copyright notice and   */
-/*      this permission notice appear in supporting documentation, and  */
-/*      that the name of Rich Gopstein and Harris Corporation not be    */
-/*      used in advertising or publicity pertaining to distribution     */
-/*      of the software without specific, written prior permission.     */
-/*      Rich Gopstein and Harris Corporation make no representations    */
-/*      about the suitability of this software for any purpose.  It     */
-/*      provided "as is" without express or implied warranty.           */
-/************************************************************************/
-
-/************************************************************************/
-/* sound2sun.c - Convert sampled audio files into uLAW format for the   */
-/*               Sparcstation 1.                                        */
-/*               Send comments to ..!rutgers!soleil!gopstein            */
-/************************************************************************/
-/*									*/
-/*  Modified November 27, 1989 to convert to 8000 samples/sec           */
-/*   (contrary to man page)                                             */
-/*  Modified December 13, 1992 to write standard Sun .au header with	*/
-/*   unspecified length.  Also made miscellaneous changes for 		*/
-/*   VMS port.  (K. S. Kubo, ken@hmcvax.claremont.edu)			*/
-/*  Fixed Bug with converting slow sample speeds			*/
-/*									*/
-/************************************************************************/
-
-
-#include <stdio.h>
-
-#define DEFAULT_FREQUENCY 11000
-
-#ifdef VAXC
-#define	READ_OPEN	"r", "mbf=16", "shr=get"
-#define WR_OPEN		"w", "mbf=16"
-#else
-#define READ_OPEN	"r"
-#define WR_OPEN		"w"
-#endif
-
-FILE *infile, *outfile;
-
-/* convert two's complement ch into uLAW format */
-
-unsigned int cvt(ch)
-int ch;
-{
-
-  int mask;
-
-  if (ch < 0) {
-    ch = -ch;
-    mask = 0x7f;
-  } else {
-    mask = 0xff;
-  }
-
-  if (ch < 32) {
-    ch = 0xF0 | 15 - (ch / 2);
-  } else if (ch < 96) {
-    ch = 0xE0 | 15 - (ch - 32) / 4;
-  } else if (ch < 224) {
-    ch = 0xD0 | 15 - (ch - 96) / 8;
-  } else if (ch < 480) {
-    ch = 0xC0 | 15 - (ch - 224) / 16;
-  } else if (ch < 992) {
-    ch = 0xB0 | 15 - (ch - 480) / 32;
-  } else if (ch < 2016) {
-    ch = 0xA0 | 15 - (ch - 992) / 64;
-  } else if (ch < 4064) {
-    ch = 0x90 | 15 - (ch - 2016) / 128;
-  } else if (ch < 8160) {
-    ch = 0x80 | 15 - (ch - 4064) /  256;
-  } else {
-    ch = 0x80;
-  }
-return (mask & ch);
-}
-
-/* write a "standard" sun header with an unspecified length */
-#define wrulong(fp, ul) putc((ul >> 24) & 0xff, fp); \
-    putc((ul >> 16) & 0xff, fp); putc((ul >> 8) & 0xff, fp); \
-    putc(ul & 0xff, fp);
-
-static void
-wr_header(optr)
-FILE *optr;
-{
-    wrulong(optr, 0x2e736e64);	/* Sun magic */
-    wrulong(optr, 24);		/* header size in bytes */
-    wrulong(optr, ((unsigned)(~0)));	/* unspecified data size */
-    wrulong(optr, 1);		/* Sun uLaw format */
-    wrulong(optr, 8000);	/* sample rate by definition :-) */
-    wrulong(optr, 1);		/* single channel */
-}
-
-/*******************************************************
-/*                                                     */
-/* Usage is "sound2sun [-f frequency] infile outfile"  */
-/*                                                     */
-/* "frequency" is the samples per second of the infile */
-/* the outfile is always 8000 samples per second.      */
-/*                                                     */
-/*******************************************************/
-
-/***********************************************************************/
-/*                                                                     */
-/* The input file is expected to be a stream of one-byte excess-128    */
-/* samples.  Each sample is converted to 2's complement by subtracting */
-/* 128, then converted to uLAW and output.  We calculate the proper    */
-/* number of input bytes to skip in order to make the sample frequency */
-/* convert to 8000/sec properly.  Interpolation could be added, but it */
-/* doesn't appear to be necessary.                                     */
-/*                                                                     */
-/***********************************************************************/
-
-
-main(argc, argv)
-int argc;
-char *argv[];
-{
-
-  float sum = 0;
-  float frequency, increment;
-
-  unsigned char ch;
-  unsigned char ulaw;
-
-  int chr;
-
-  if ((argc != 3) && (argc != 5)) {
-    fprintf(stderr,"Usage: sound2sun [-f frequency] infile outfile\n");
-    exit(1);
-  }
-
-  if (argc == 5) {
-    if (strcmp(argv[1], "-f") != 0) {
-      fprintf(stderr, "Usage: sound2sun [-f frequency] infile outfile\n");
-      exit(1);
-    } else {
-      frequency = atoi(argv[2]);
-    }
-  } else {
-    frequency = DEFAULT_FREQUENCY;
-  }
-
-  if ((infile = fopen(argv[argc-2], READ_OPEN)) == NULL) {
-    perror("Error opening infile");
-    exit(0);
-  }
-
-  if ((outfile = fopen(argv[argc-1], WR_OPEN)) == NULL) {
-    perror("Error opening outfile");
-    exit(0);
-  }
-
-  wr_header(outfile);
-
-  /* increment is the number of bytes to read each time */
-
-  increment = frequency / 8000;
-
-  ch = fgetc(infile);
-
-  while (!feof(infile)) {
-
-    /* convert the excess 128 to two's complement */
-
-    chr = 0x80 - ch;
-
-    /* increase the volume */
-    /* convert to uLAW */
-
-    ulaw = cvt(chr * 16);
-
-    /* output it */
-
-    fputc((char) ulaw, outfile);
-
-    /* skip enough input bytes to compensate for sampling frequency diff */
-
-    sum += increment;
-
-    while(sum > 0) {
-      if (!feof(infile)) ch = fgetc(infile);
-      sum--;
-    }
-
-  }
-
-  fclose(infile);
-  fclose(outfile);
-}
-
-/*  DEC/CMS REPLACEMENT HISTORY, Element SOUND2SUN.C */
-/*  *1    14-DEC-1992 17:46:37 CENYDD "main program" */
-/*  DEC/CMS REPLACEMENT HISTORY, Element SOUND2SUN.C */
--- a/sound2sun.opt
+++ /dev/null
@@ -1,5 +1,0 @@
-identification="V1.0"
-!
-! Basic C library stuff
-!
-sys$share:vaxcrtl/shareable
--- a/sox.1
+++ b/sox.1
@@ -9,7 +9,7 @@
 .if t .sp .5v
 .if n .sp
 ..
-.TH SoX 1 "June 28, 1999"
+.TH SoX 1 "November 8, 1999"
 .SH NAME
 sox \- Sound eXchange : universal sound sample translator
 .SH SYNOPSIS
@@ -69,6 +69,8 @@
 .br
 	echos \fIgain-in gain-out delay decay\fB [ \fIdelay decay ...\fB]
 .br
+	filter \fB[ \fIlow\fB ]\fI-\fB[ \fIhigh\fB ] [ \fIwindow-len\fB [ \fIbeta\fB ]]
+.br
 	flanger \fIgain-in gain-out delay decay speed -s\fB | -fI-t\fB
 .br
 	highp \fIcenter\fB
@@ -456,12 +458,12 @@
 of the sample file must be given.
 The number of channels defaults to 1.
 .TP 10
-.B ".ub, .sb, .uw, .sw, .ul"
+.B ".ub, .sb, .uw, .sw, .ul, .sl"
 These are several suffices which serve as
 a shorthand for raw files with a given size and style.
-Thus, \fBub, sb, uw, sw,\fR and \fBul\fR
+Thus, \fBub, sb, uw, sw, ul\fR and \fBsl\fR
 correspond to "unsigned byte", "signed byte",
-"unsigned word", "signed word", and "ulaw" (byte).
+"unsigned word", "signed word", "ulaw" (byte), and "signed long".
 The sample rate defaults to 8000 hz if not explicitly set,
 and the number of channels (as always) defaults to 1.
 There are lots of Sparc samples floating around in u-law format
@@ -513,11 +515,16 @@
 .I -n
 (for noise) option uses the alternate mode
 for un-pitched signals.
+.B Warning:
+.I -n
+introduces a power-gain of about 11dB in the filter, so beware
+of output clipping.
 .B Band
 introduces noise in the shape of the filter,
 i.e. peaking at the 
 .I center
 frequency and settling around it.
+See \fBfilter\fR for a bandpass effect with steeper shoulders.
 .TP
 chorus \fIgain-in gain-out delay decay speed deptch 
 .TP 10
@@ -582,6 +589,24 @@
 and the decay (relative to gain-in) of that echo.
 Gain-out is the volume of the output.
 .TP 10
+filter [ \fIlow\fR ]-[ \fIhigh\fR ] [ \fIwindow-len\fR [ \fIbeta\fR ] ]
+Apply a Sinc-windowed lowpass, highpass, or bandpass filter of given
+window length to the signal.
+\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.
+
+A lowpass filter is obtained by leaving \fIlow\fR unspecified, or 0.
+A highpass filter is obtained by leaving \fIhigh\fR unspecified, or 0,
+or greater than or equal to the Nyquist freq.
+
+The \fIwindow-len\fR, if unspecified, defaults to 128.
+Longer windows give a sharper cutoff, smaller windows a more gradual cutoff.
+
+The \fIbeta\fR, if unspecified, defaults to 16.  This selects a Kaiser window.
+You can select a Nuttall window by specifying anything <= 2.0 here.
+For more discussion of beta, look under the \fBresample\fR effect.
+
+.TP 10
 flanger \fIgain-in gain-out delay decay speed -s \fR| \fI-t
 Add a flanger to a sound sample.  Each triple
 delay/decay/speed gives the delay in milliseconds
@@ -596,6 +621,7 @@
 .I center
 frequency in the middle of the drop.
 The slope of the filter is quite gentle.
+See \fBfilter\fR for a highpass effect with sharper cutoff.
 .TP 10
 lowp \fIcenter
 Apply a low-pass filter.
@@ -603,6 +629,7 @@
 .I center
 frequency in the middle of the drop.
 The slope of the filter is quite gentle.
+See \fBfilter\fR for a lowpass effect with sharper cutoff.
 .TP 10
 map 
 Display a list of loops in a sample,
@@ -679,25 +706,53 @@
 .B Sox's
 rate changing effects to ues, you will want to read a
 detailed analysis of all of them at http://eakaw2.et.tu-dresden.de/~andreas/resample/resample.html
+[Nov,1999: These tests need to be updated for sox-12.18, which has bugfixes to the
+resample and polyphase code.]
 .TP 10
-resample [ \fIrolloff\fR [ \fIbeta\fR ] ]
+resample [ \fI-qs\fB | \fI-q\fB | \fI-ql\fB ] [ \fIrolloff\fB [ \fIbeta\fB ] ]\fR
 Translate input sampling rate to output sampling rate
 via simulated analog filtration.
 This method is slower than 
 .B rate,
-but gives much
-better results.  rolloff refers to the cut-off frequency of the
+but gives much better results.
+
+The \fI-qs\fR, \fI-q\fR, or \fI-ql\fR options specify increased accuracy
+at the cost of lower execution speed.  By default, linear interpolation
+is used, with a window width about 37 samples at the lower rate.
+This gives an accuracy of about 16 bits, but insufficient stopband rejection
+in the case that you want to have rolloff greater than about 0.85 of
+the Nyquist frequency.
+The \fI-q*\fR options use quadratic interpolation of filter
+coefficients, resulting in about 22 bits precision.
+\fI-qs\fR, \fI-q\fR, or \fI-ql\fR use window lengths of 37, 75, or 150
+samples, respectively, at the lower sample-rate of the two files.
+This means progressively sharper stop-band rejection, at proportionally
+slower execution times.
+
+\fIrolloff\fR refers to the cut-off frequency of the
 low pass filter and is given in terms of the
-Nyquist frequency for the lower sample rate.  rolloff therefor should
-be something between 0. and 1., in practice 0.8-0.95.  beta trades stop band
-rejection against transition width from passband to stop band.  Larger
-beta means a slower transition and greater stopband rejection.  beta
-should be at least greater than 2.  The default is rollof 0.8, beta 17.5,
-which is rather conservative with respect to aliasing.  Lower beta
-and higher rolloff values preserve more high frequency signal energy,
-but introduce measurable artifacts.
-This is the default effect 
-if the two files have different sampling rates.
+Nyquist frequency for the lower sample rate.  rolloff therefore should
+be something between 0. and 1., in practice 0.8-0.95.  The default is 0.8.
+
+The \fIbeta\fR parameter
+determines the type of filter window used.  Any value greater than 2.0 is
+the beta for a Kaiser window.  Beta <= 2.0 selects a Nuttall window.
+If unspecified, the default is a Kaiser window with beta 16.
+
+In the case of Kaiser window beta > 2.0, lower betas produce a somewhat
+faster transition from passband to stopband, 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 cutoff, don't use low beta's, use a longer sample window.
+A Nuttall window is selected by specifying any 'beta' <= 2, and the
+Nuttall window has somewhat steeper cutoff 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 Nuttall vs. Kaiser windows.
+
+This is the default effect if the two files have different sampling rates.
+Default parameters are Kaiser window of length 37, rolloff 0.80, beta 16,
+linear interpolation.  \fI-qs\fR is only slightly slower, but more accurate for
+16-bit or higher precision.
+
 .TP 10
 reverb \fIgain-out delay \fR[ \fIdelay ... \fR]
 Add reverbation to a sound sample.  Each delay is given 
--- a/sox.opt
+++ /dev/null
@@ -1,9 +1,0 @@
-identification="V5.7"
-!
-! SoundTools library
-!
-soundtools.olb/library
-!
-! Basic C library stuff
-!
-sys$share:vaxcrtl/shareable
--- a/sox.txt
+++ b/sox.txt
@@ -1,848 +1,858 @@
 
 
 
-SoX(1)							   SoX(1)
+User Commands						   SoX(1)
 
 
+
 NAME
-       sox - Sound eXchange : universal sound sample translator
+     sox - Sound eXchange : universal sound sample translator
 
 SYNOPSIS
-       sox infile outfile
-       sox infile outfile [ effect [ effect options ... ] ]
-       sox infile -e effect [ effect options ... ]
-       sox  [ general options  ] [ format options  ] ifile [ for-
-       mat options  ] ofile [ effect [ effect options ... ] ]
+     sox infile	outfile
+     sox infile	outfile	[ effect [ effect options ... ]	]
+     sox infile	-e effect [ effect options ... ]
+     sox [ general options  ] [	format options	] ifile	[  format
+     options  ]	ofile [	effect [ effect	options	... ] ]
 
-       General options: [ -e ] [ -h ] [ -p ] [ -v volume ] [ -V ]
+     General options:  [ -e ] [	-h ] [ -p ] [ -v volume	] [ -V ]
 
-       Format	options:   [   -t  filetype  ]	[  -r  rate  ]	[
-       -s/-u/-U/-A/-a/-g ] [ -b/-w/-l/-f/-d/-D ] [ -c channels	]
-       [ -x ]
+     Format options:  [	-t filetype ] [	-r rate	 ]  [  -s/-u/-U/-
+     A/-a/-g ] [ -b/-w/-l/-f/-d/-D ] [ -c channels ] [ -x ]
 
-       Effects:
-	    avg [ -l | -r ]
-	    band [ -n ] center [ width ]
-	    check
-	    chorus  gain-in  gain  out	delay  decay  speed depth
-		 -s | -t [ delay decay speed depth -s | -fI-t ]
-	    compand attack1,decay1[,attack2,decay2...]
-		    in-dB1,out-dB1[,in-dB2,out-dB2...]
-		    [gain] [initial-volume]
-	    copy
-	    cut
-	    deemph
-	    echo gain-in gain-out delay decay [ delay decay  ...]
-	    echos gain-in gain-out delay decay [ delay decay ...]
-	    flanger gain-in gain-out delay decay speed -s | -fI-t
-	    highp center
-	    lowp center
-	    map
-	    mask
-	    phaser gain-in gain-out delay decay speed -s | -t
-	    pick
-	    polyphase [ -w < num / ham > ]
-		      [	 -width <  long	 / short  / # > ]
-		      [ -cutoff #  ]
-	    rate
-	    resample
-	    reverb gain-out reverb-time delay [ delay ... ]
-	    reverse
-	    split
-	    stat [ debug | -v ]
-	    swap [ 1 2 3 4 ]
-	    vibro speed [ depth ]
+     Effects:
+	  avg [	-l | -r	]
+	  band [ -n ] center [ width ]
+	  check
+	  chorus  gain-in  gain	 out  delay  decay  speed   depth
+	       -s | -t [ delay decay speed depth -s | -fI-t ]
+	  compand attack1,decay1[,attack2,decay2...]
+		  in-dB1,out-dB1[,in-dB2,out-dB2...]
+		  [gain] [initial-volume]
+	  copy
+	  cut
+	  deemph
+	  echo gain-in gain-out	delay decay [ delay decay ...]
+	  echos	gain-in	gain-out delay decay [ delay decay ...]
+	  filter [ low ]-[ high	] [ window-len [ beta ]]
+	  flanger gain-in gain-out delay decay speed -s	| -fI-t
+	  highp	center
+	  lowp center
+	  map
+	  mask
+	  phaser gain-in gain-out delay	decay speed -s | -t
+	  pick
+	  polyphase [ -w < num / ham > ]
+		    [  -width <	 long  / short	/ # > ]
+		    [ -cutoff #	 ]
+	  rate
+	  resample
+	  reverb gain-out reverb-time delay [ delay ...	]
+	  reverse
+	  split
+	  stat [ debug | -v ]
+	  swap [ 1 2 3 4 ]
+	  vibro	speed [	depth ]
 
 DESCRIPTION
-       Sox  translates	sound  files  from one format to another,
-       possibly doing a sound effect.
+     Sox translates sound files	from one format	to another,  pos-
+     sibly doing a sound effect.
 
 
 
+SunOS 5.6	  Last change: November	8, 1999			1
 
 
-			  June 28, 1999				1
 
 
 
 
+User Commands						   SoX(1)
 
-SoX(1)							   SoX(1)
 
 
 OPTIONS
-       The option syntax is a little grotty, but in essence:
-	    sox file.au file.voc
-       translates a sound sample in SUN Sparc .AU format  into	a
-       SoundBlaster .VOC file, while
-	    sox -v 0.5 file.au -r 12000 file.voc rate
-       does  the  same	format	translation  but  also lowers the
-       amplitude by 1/2 and changes the sampling rate  from  8000
-       hertz to 12000 hertz via the rate sound effect loop.
+     The option	syntax is a little grotty, but in essence:
+	  sox file.au file.voc
+     translates	a sound	sample in SUN Sparc  .AU  format  into	a
+     SoundBlaster .VOC file, while
+	  sox -v 0.5 file.au -r	12000 file.voc rate
+     does the same format translation but also lowers the  ampli-
+     tude by 1/2 and changes the sampling rate from 8000 hertz to
+     12000 hertz via the rate sound effect loop.
 
-       Format options:
+     Format options:
 
-       Format  options	effect	the  file  that	 they immediately
-       percede.	 If they are placed before the	input  file  name
-       then  they  effect  the	input  data.   If they are placed
-       before the output file name then they will effect the out-
-       put data.  It is also possible to read a given file in and
-       output it in any supported data format by specifying  out-
-       put format options.
+     Format options effect the file that  they	immediately  per-
+     cede.   If	 they  are placed before the input file	name then
+     they effect the input data.  If they are placed  before  the
+     output  file name then they will effect the output	data.  It
+     is	also possible to read a	given file in and  output  it  in
+     any  supported  data  format  by  specifying  output  format
+     options.
 
-       -t filetype
-		 gives the type of the sound sample file.
+     -t	filetype
+	       gives the type of the sound sample file.
 
-       -r rate	 Give sample rate in Hertz of file.  To cause the
-		 output file to have a different sample rate then
-		 the  input  file,  include  this option with the
-		 appropriate rate value	 along	with  the  output
-		 options.   If	the  input  and output files have
-		 different rates then a sample rate change effect
-		 must  be  ran.	 If a sample rate changing effect
-		 is not specified then a default one will be used
-		 with its default parameters.
+     -r	rate   Give sample rate	in Hertz of file.  To  cause  the
+	       output  file  to	have a different sample	rate then
+	       the input  file,	 include  this	option	with  the
+	       appropriate  rate  value	 along	with  the  output
+	       options.	 If the	input and output files have  dif-
+	       ferent rates then a sample rate change effect must
+	       be ran.	If a sample rate changing effect  is  not
+	       specified then a	default	one will be used with its
+	       default parameters.
 
-       -s/-u/-U/-A/-a/-g
-		 The  sample  data  is signed linear (2's comple-
-		 ment), unsigned linear, U-law (logarithmic),  A-
-		 law  (logarithmic), ADPCM, or GSM.  U-law and A-
-		 law are the U.S. and international standards for
-		 logarithmic  telephone sound compression.  ADPCM
-		 is form of sound compression  that  has  a  good
-		 compromise  between  good sound quality and fast
-		 encoding/decoding time.  GSM is a standard  used
-		 for  telephone	 sound	compression  in	 European
-		 countries and its gaining popularity because  of
-		 its quality.
+     -s/-u/-U/-A/-a/-g
+	       The sample data is signed linear	(2's complement),
+	       unsigned	linear,	U-law (logarithmic), A-law (loga-
+	       rithmic), ADPCM,	or GSM.	 U-law and A-law are  the
+	       U.S.  and  international	standards for logarithmic
+	       telephone sound compression.   ADPCM  is	 form  of
+	       sound  compression  that	 has  a	 good  compromise
+	       between	  good	  sound	   quality    and    fast
+	       encoding/decoding  time.	  GSM  is a standard used
+	       for telephone sound compression in European  coun-
+	       tries  and  its	gaining	popularity because of its
+	       quality.
 
-       -b/-w/-l/-f/-d/-D
-		 The  sample  data  is	in  bytes,  16-bit words,
-		 32-bit longwords, 32-bit floats,  64-bit  double
-		 floats,  or 80-bit IEEE floats.  Floats and dou-
-		 ble floats are in native machine format.
+     -b/-w/-l/-f/-d/-D
+	       The sample data is in bytes, 16-bit words,  32-bit
+	       longwords, 32-bit floats, 64-bit	double floats, or
+	       80-bit IEEE floats.  Floats and double floats  are
+	       in native machine format.
 
-       -x	 The sample data is in XINU format; that  is,  it
-		 comes	from  a	 machine  with	the opposite word
 
 
 
-			  June 28, 1999				2
+SunOS 5.6	  Last change: November	8, 1999			2
 
 
 
 
 
-SoX(1)							   SoX(1)
 
+User Commands						   SoX(1)
 
-		 order than yours and must be  swapped	according
-		 to  the  word-size given above.  Only 16-bit and
-		 32-bit integer data may  be  swapped.	 Machine-
-		 format	 floating-point	 data  is  not	portable.
-		 IEEE floats are a fixed, portable format.
 
-       -c channels
-		 The number of sound channels in the  data  file.
-		 This  may  be	1,  2, or 4; for mono, stereo, or
-		 quad sound data.  To cause the	 output	 file  to
-		 have  a  different  number  of channels then the
-		 input file, include this option with the  appro-
-		 raite	value  with  the output file options.  If
-		 the input and output file have a different  num-
-		 ber  of  channels  then  the  avg effect must be
-		 used.	If the avg effect is not specified on the
-		 command  line	it  will  be invoked with default
-		 parameters.
 
-       General options:
+     -x	       The sample data is in XINU  format;  that  is,  it
+	       comes  from a machine with the opposite word order
+	       than yours and must be swapped  according  to  the
+	       word-size  given	 above.	  Only	16-bit and 32-bit
+	       integer	data  may  be  swapped.	   Machine-format
+	       floating-point  data is not portable.  IEEE floats
+	       are a fixed, portable format.
 
-       -e	 after the input file allows you to avoid  giving
-		 an output file and just name an effect.  This is
-		 mainly useful with the stat effect  but  can  be
-		 used with others.
+     -c	channels
+	       The number of sound channels  in	 the  data  file.
+	       This  may be 1, 2, or 4;	for mono, stereo, or quad
+	       sound data.  To cause the output	file  to  have	a
+	       different  number of channels then the input file,
+	       include this option with	the approraite value with
+	       the  output  file options. If the input and output
+	       file have a different number of channels	then  the
+	       avg effect must be used.	 If the	avg effect is not
+	       specified on the	command	line it	will  be  invoked
+	       with default parameters.
 
-       -h	 Print version number and usage information.
+     General options:
 
-       -p	 Run  in  preview  mode	 and run fast.	This will
-		 somewhat speed up sox when the output format has
-		 a  different  number of channels and a different
-		 rate then the input file.  The	 order	that  the
-		 effects  are run in will be arranged for maximum
-		 speed and not quality.
+     -e	       after the input file allows you to avoid	giving an
+	       output  file  and  just	name  an effect.  This is
+	       mainly useful with the stat effect but can be used
+	       with others.
 
-       -v volume Change amplitude (floating point); less than 1.0
-		 decreases, greater than 1.0 increases.	 Note: we
-		 perceive volume logarithmically,  not	linearly.
-		 Note: see the stat effect.
+     -h	       Print version number and	usage information.
 
-       -V	 Print	a description of processing phases.  Use-
-		 ful for figuring out exactly how sox is mangling
-		 your sound samples.
+     -p	       Run in preview mode and run fast.  This will some-
+	       what  speed  up	sox  when the output format has	a
+	       different number	of channels and	a different  rate
+	       then  the  input	file.  The order that the effects
+	       are run in will be arranged for maximum speed  and
+	       not quality.
 
-       The  input and output files may be standard input and out-
-       put.  This is specified by '-'.	The -t type  option  must
-       be  given  in this case, else sox will not know the format
-       of   the	  given	  file.	   The	 -t,   -r,   -s/-u/-U/-A,
-       -b/-w/-l/-f/-d/-D  and  -x options refer to the input data
-       when given before the input file name.  After, they  refer
-       to the output data.
+     -v	volume Change amplitude	(floating point); less	than  1.0
+	       decreases,  greater  than 1.0 increases.	 Note: we
+	       perceive	 volume	 logarithmically,  not	linearly.
+	       Note: see the stat effect.
 
-       If  you don't give an output file name, sox will just read
-       the input file.	This is useful for validating  structured
+     -V	       Print a description of processing phases.   Useful
+	       for  figuring out exactly how sox is mangling your
+	       sound samples.
 
+     The input and output files	may be standard	input and output.
+     This  is specified	by '-'.	 The -t	type option must be given
+     in	this case, else	sox will not know the format of	the given
+     file.   The  -t,  -r,  -s/-u/-U/-A, -b/-w/-l/-f/-d/-D and -x
+     options refer to the input	data when given	before the  input
+     file name.	 After,	they refer to the output data.
 
 
-			  June 28, 1999				3
 
 
+SunOS 5.6	  Last change: November	8, 1999			3
 
 
 
-SoX(1)							   SoX(1)
 
 
-       file  formats; the stat effect may also be used via the -e
-       option.
 
+User Commands						   SoX(1)
+
+
+
+     If	you don't give an output file name, sox	 will  just  read
+     the  input	 file.	 This is useful	for validating structured
+     file formats; the stat effect may also be used  via  the  -e
+     option.
+
 FILE TYPES
-       Sox needs to know the formats  of  the  input  and  output
-       files.	File  formats  which have headers are checked, if
-       that header doesn't seem right, the program exits with  an
-       appropriate  message.   Currently,  raw (no header) binary
-       and textual data, Amiga 8SVX, Apple/SGI	AIFF,  SPARC  .AU
-       (w/header),  AVR,  NeXT	.SND,  CD-R, CVSD, GSM 06.10, Mac
-       HCOM, Sound Tools MAUD, OSS device drivers,  Turtle  Beach
-       .SMP,  Sound  Blaster,  Sndtool,	 and  Sounder,	Sun Audio
-       device driver, Yamaha TX-16W Sampler, IRCAM  Sound  Files,
-       Creative	 Labs VOC, Psion .WVE, and Microsoft RIFF/WAV are
-       supported.
+     Sox needs to know the formats of the input	and output files.
+     File  formats which have headers are checked, if that header
+     doesn't seem right, the program exits  with  an  appropriate
+     message.	Currently,  raw	 (no  header)  binary and textual
+     data, Amiga 8SVX, Apple/SGI AIFF, SPARC .AU (w/header), AVR,
+     NeXT  .SND,  CD-R,	 CVSD,	GSM  06.10, Mac	HCOM, Sound Tools
+     MAUD, OSS device drivers, Turtle Beach .SMP, Sound	 Blaster,
+     Sndtool, and Sounder, Sun Audio device driver, Yamaha TX-16W
+     Sampler, IRCAM Sound Files,  Creative Labs	VOC, Psion  .WVE,
+     and Microsoft RIFF/WAV are	supported.
 
+     .8svx     Amiga 8SVX musical instrument description format.
 
-       .8svx	 Amiga 8SVX musical instrument	description  for-
-		 mat.
+     .aiff     AIFF files used on Apple	IIc/IIgs and SGI.   Note:
+	       the  AIFF format	supports only one SSND chunk.  It
+	       does not	support	multiple  sound	 chunks,  or  the
+	       8SVX  musical instrument	description format.  AIFF
+	       files are multimedia archives  and  and	can  have
+	       multiple	audio and picture chunks.  You may need	a
+	       separate	archiver to work with them.
 
-       .aiff	 AIFF  files  used  on	Apple  IIc/IIgs	 and SGI.
-		 Note: the AIFF format	supports  only	one  SSND
-		 chunk.	  It  does  not	 support  multiple  sound
-		 chunks, or the 8SVX musical instrument	 descrip-
-		 tion format.  AIFF files are multimedia archives
-		 and and can  have  multiple  audio  and  picture
-		 chunks.   You	may  need  a separate archiver to
-		 work with them.
+     .au       SUN Microsystems	AU files.  There  are  apparently
+	       many  types of .au files; DEC has invented its own
+	       with a different	magic number and word order.  The
+	       .au  handler  can  read	these  files but will not
+	       write them.  Some .au files have	valid AU  headers
+	       and some	do not.	 The latter are	probably original
+	       SUN u-law 8000 hz samples.   These  can	be  dealt
+	       with using the .ul format (see below).
 
-       .au	 SUN Microsystems AU files.  There are apparently
-		 many  types  of  .au files; DEC has invented its
-		 own with  a  different	 magic	number	and  word
-		 order.	 The .au handler can read these files but
-		 will not write them.  Some .au files have  valid
-		 AU  headers  and  some	 do  not.  The latter are
-		 probably original SUN	u-law  8000  hz	 samples.
-		 These	can  be	 dealt	with using the .ul format
-		 (see below).
+     .avr      Audio Visual Research
+	       The AVR format is produced by a number of  commer-
+	       cial packages on	the Mac.
 
-       .avr	 Audio Visual Research
-		 The AVR format is produced by a number	 of  com-
-		 mercial packages on the Mac.
+     .cdr      CD-R
+	       CD-R files are used  in	mastering  music  Compact
+	       Disks.	The  file format is, as	you might expect,
+	       raw stereo raw unsigned samples	at  44khz.   But,
+	       there's	some  blocking/padding oddity in the for-
+	       mat, so it needs	its own	handler.
 
-       .cdr	 CD-R
-		 CD-R  files  are used in mastering music Compact
-		 Disks.	 The file format is, as you might expect,
-		 raw  stereo raw unsigned samples at 44khz.  But,
-		 there's some blocking/padding oddity in the for-
-		 mat, so it needs its own handler.
+     .cvs      Continuously Variable Slope Delta modulation
+	       Used to compress	 speech	 audio	for  applications
+	       such as voice mail.
 
-       .cvs	 Continuously Variable Slope Delta modulation
-		 Used  to  compress speech audio for applications
-		 such as voice mail.
+     .dat      Text Data files
 
 
 
+SunOS 5.6	  Last change: November	8, 1999			4
 
-			  June 28, 1999				4
 
 
 
 
 
-SoX(1)							   SoX(1)
+User Commands						   SoX(1)
 
 
-       .dat	 Text Data files
-		 These files contain a textual representation  of
-		 the  sample  data.   There  is	 one  line at the
-		 beginning that contains the sample rate.  Subse-
-		 quent	lines contain two numeric data items: the
-		 time since the beginning of the sample	 and  the
-		 sample value.	Values are normalized so that the
-		 maximum and minimum are 1.00  and  -1.00.   This
-		 file format can be used to create data files for
-		 external programs such as FFT analyzers or graph
-		 routines.   SoX  can also convert a file in this
-		 format back into one of the other file	 formats.
 
-       .gsm	 GSM 06.10 Lossy Speech Compression
-		 A  standard for compressing speech which is used
-		 in the Global Standard for Mobil  telecommunica-
-		 tions	(GSM).	Its good for its purpose, shrink-
-		 ing audio data size, but it will introduce  lots
-		 of  noise  when  a given sound sample is encoded
-		 and decoded multiple times.  This format is used
-		 by  some  voice mail applications.  It is rather
-		 CPU intensive.	  GSM  in  sox	is  optional  and
-		 requires  access to an external GSM library.  To
-		 see if there is support for gsm run sox  -h  and
-		 look  for  it	under  the list of supported file
-		 formats.
+	       These files contain a  textual  representation  of
+	       the  sample data.  There	is one line at the begin-
+	       ning that contains the  sample  rate.   Subsequent
+	       lines  contain  two  numeric  data items: the time
+	       since the beginning of the sample and  the  sample
+	       value.	Values are normalized so that the maximum
+	       and minimum are 1.00 and	-1.00.	This file  format
+	       can be used to create data files	for external pro-
+	       grams such as FFT  analyzers  or	 graph	routines.
+	       SoX  can	 also  convert a file in this format back
+	       into one	of the other file formats.
 
-       .hcom	 Macintosh HCOM files.	 These	are  (apparently)
-		 Mac FSSD files with some variant of Huffman com-
-		 pression.  The Macintosh has wacky file  formats
-		 and  this format handler apparently doesn't han-
-		 dle all the ones it should.  Mac users will need
-		 your  usual  arsenal  of file converters to deal
-		 with an HCOM file under Unix or DOS.
+     .gsm      GSM 06.10 Lossy Speech Compression
+	       A standard for compressing speech which is used in
+	       the  Global  Standard for Mobil telecommunications
+	       (GSM).  Its good	for its	purpose, shrinking  audio
+	       data  size,  but	 it  will introduce lots of noise
+	       when a given sound sample is encoded  and  decoded
+	       multiple	times.	This format is used by some voice
+	       mail applications.  It is  rather  CPU  intensive.
+	       GSM  in	sox is optional	and requires access to an
+	       external	GSM library.  To see if	there is  support
+	       for  gsm	run sox	-h and look for	it under the list
+	       of supported file formats.
 
-       .maud	 An Amiga format
-		 An IFF-conform sound file type, registered by MS
-		 MacroSystem  Computer GmbH, published along with
-		 the "Toccata" sound-card on the  Amiga.   Allows
-		 8bit  linear, 16bit linear, A-Law, u-law in mono
-		 and stereo.
+     .hcom     Macintosh HCOM files.  These are	(apparently)  Mac
+	       FSSD  files  with some variant of Huffman compres-
+	       sion.  The Macintosh has	wacky  file  formats  and
+	       this  format handler apparently doesn't handle all
+	       the ones	it should.   Mac  users	 will  need  your
+	       usual  arsenal  of file converters to deal with an
+	       HCOM file under Unix or DOS.
 
-       ossdsp	 OSS /dev/dsp device driver
-		 This is a psuedo-file type and can be optionally
-		 compiled  into	 Sox.	Run  sox -h to see if you
-		 have support for  this	 file  type.   When  this
-		 driver	 is used it allows you to open up the OSS
-		 /dev/dsp file and configure it to use	the  same
-		 data  type  as	 passed	 in to Sox.  It works for
-		 both playing and recording sound samples.   When
-		 playing  sound	 files	it attempts to set up the
-		 OSS driver to use the same format as  the  input
-		 file.	 It  is	 suggested to always override the
-		 output values to use the highest quality samples
+     .maud     An Amiga	format
+	       An IFF-conform sound file type, registered  by  MS
+	       MacroSystem  Computer  GmbH,  published along with
+	       the "Toccata" sound-card	 on  the  Amiga.   Allows
+	       8bit  linear,  16bit  linear, A-Law, u-law in mono
+	       and stereo.
 
+     ossdsp    OSS /dev/dsp device driver
+	       This is a psuedo-file type and can  be  optionally
+	       compiled	 into Sox.  Run	sox -h to see if you have
+	       support for this	file type.  When this  driver  is
+	       used  it	 allows	 you  to open up the OSS /dev/dsp
+	       file and	configure it to	use the	same data type as
+	       passed  in  to  Sox. It works for both playing and
+	       recording sound samples.	 When playing sound files
+	       it  attempts  to	 set up	the OSS	driver to use the
+	       same format as the input	file.  It is suggested to
+	       always  override	 the  output  values  to  use the
+	       highest	quality	 samples  your	sound  card   can
 
 
-			  June 28, 1999				5
 
+SunOS 5.6	  Last change: November	8, 1999			5
 
 
 
 
-SoX(1)							   SoX(1)
 
 
-		 your  sound card can handle.  Example: -t ossdsp
-		 -w -s /dev/dsp
+User Commands						   SoX(1)
 
-       .sf	 IRCAM Sound Files.
-		 SoundFiles are used by academic  music	 software
-		 such  as  the	CSound	package,  and the MixView
-		 sound sample editor.
 
-       .smp	 Turtle Beach SampleVision files.
-		 SMP files are for use with  the  PC-DOS  package
-		 SampleVision  by  Turtle  Beach  Softworks. This
-		 package is for	 communication	to  several  MIDI
-		 samplers.  All sample rates are supported by the
-		 package, although not all are supported  by  the
-		 samplers  themselves.	Currently loop points are
-		 ignored.
 
-       sunau	 Sun /dev/audio device driver
-		 This is a psuedo-file type and can be optionally
-		 compiled  into	 Sox.	Run  sox -h to see if you
-		 have support for  this	 file  type.   When  this
-		 driver	 is  used  it allows you to open up a Sun
-		 /dev/audio file and configure it to use the same
-		 data  type  as	 passed	 in to Sox.  It works for
-		 both playing and recording sound samples.   When
-		 playing  sound	 files	it attempts to set up the
-		 audio driver to use the same format as the input
-		 file.	 It  is	 suggested to always override the
-		 output values to use the highest quality samples
-		 your  hardware can handle.  Example: -t sunau -w
-		 -s /dev/audio or -t sunau -U -c 1 /dev/audio for
-		 older sun equipment.
+	       handle.	Example:  -t ossdsp -w -s /dev/dsp
+
+     .sf       IRCAM Sound Files.
+	       SoundFiles are used  by	academic  music	 software
+	       such  as	the CSound package, and	the MixView sound
+	       sample editor.
+
+     .smp      Turtle Beach SampleVision files.
+	       SMP files are for use with the PC-DOS package Sam-
+	       pleVision  by Turtle Beach Softworks. This package
+	       is for communication to several MIDI samplers. All
+	       sample	rates	are  supported	by  the	 package,
+	       although	not all	are  supported	by  the	 samplers
+	       themselves. Currently loop points are ignored.
 
-       .txw	 Yamaha TX-16W sampler.
-		 A  file  format  from a Yamaha sampling keyboard
-		 which wrote IBM-PC format 3.5"	 floppies.   Han-
-		 dles reading of files which do not have the sam-
-		 ple rate field set to one  of	the  expected  by
-		 looking  at  some other bytes in the attack/loop
-		 length fields, and defaulting to  33kHz  if  the
-		 sample rate is still unknown.
+     sunau     Sun /dev/audio device driver
+	       This is a psuedo-file type and can  be  optionally
+	       compiled	 into Sox.  Run	sox -h to see if you have
+	       support for this	file type.  When this  driver  is
+	       used  it	 allows	 you  to open up a Sun /dev/audio
+	       file and	configure it to	use the	same data type as
+	       passed  in  to  Sox. It works for both playing and
+	       recording sound samples.	 When playing sound files
+	       it  attempts to set up the audio	driver to use the
+	       same format as the input	file.  It is suggested to
+	       always  override	 the  output  values  to  use the
+	       highest quality samples your hardware can  handle.
+	       Example:	 -t sunau -w -s	/dev/audio or -t sunau -U
+	       -c 1 /dev/audio for older sun equipment.
 
-       .vms	 More info to come.
-		 Used  to  compress speech audio for applications
-		 such as voice mail.
+     .txw      Yamaha TX-16W sampler.
+	       A file format  from  a  Yamaha  sampling	 keyboard
+	       which  wrote IBM-PC format 3.5" floppies.  Handles
+	       reading of files	which do not have the sample rate
+	       field  set  to  one  of the expected by looking at
+	       some other bytes	in the attack/loop length fields,
+	       and  defaulting	to  33kHz  if  the sample rate is
+	       still unknown.
 
-       .voc	 Sound Blaster VOC files.
-		 VOC files are	multi-part  and	 contain  silence
-		 parts,	 looping,  and different sample rates for
-		 different chunks.  On input, the  silence  parts
-		 are  filled  out, loops are rejected, and sample
-		 data  with  a	new  sample  rate  is	rejected.
-		 Silence  with	a different sample rate is gener-
-		 ated appropriately.  On output, silence  is  not
+     .vms      More info to come.
+	       Used to compress	 speech	 audio	for  applications
+	       such as voice mail.
 
+     .voc      Sound Blaster VOC files.
+	       VOC  files  are	multi-part  and	 contain  silence
+	       parts,  looping,	 and  different	 sample	rates for
+	       different chunks.  On input, the	silence	parts are
+	       filled  out,  loops  are	rejected, and sample data
+	       with a new sample rate is rejected.  Silence  with
+	       a  different  sample  rate  is generated	appropri-
+	       ately.  On output, silence is  not  detected,  nor
+	       are impossible sample rates.
 
 
-			  June 28, 1999				6
 
+SunOS 5.6	  Last change: November	8, 1999			6
 
 
 
 
-SoX(1)							   SoX(1)
 
 
-		 detected, nor are impossible sample rates.
+User Commands						   SoX(1)
 
-       .wav	 Microsoft .WAV RIFF files.
-		 These	appear	to  be very similar to IFF files,
-		 but not the same.  They  are  the  native  sound
-		 file format of Windows.  (Obviously, Windows was
-		 of such incredible importance	to  the	 computer
-		 industry  that it just had to have its own sound
-		 file format.)	Normally .wav files have all for-
-		 matting  information in their headers, and so do
-		 not need any format  options  specified  for  an
-		 input	file.  If any are, they will override the
-		 file header, and you  will  be	 warned	 to  this
-		 effect.  You had better know what you are doing!
-		 Output format options will cause a  format  con-
-		 version,  and	the  .wav  will written appropri-
-		 ately.	 Note that it is possible to  write  data
-		 of  a	type that cannot be specified by the .wav
-		 header, and you will be warned that you a  writ-
-		 ing  a	 bad  file !  Sox currently can read PCM,
-		 ULAW, ALAW, MS ADPCM, and IMA	(or  DVI)  ADPCM.
-		 It  can  output  all of these formats except the
-		 ADPCM styles.
 
-       .wve	 Psion 8-bit alaw
-		 These are 8-bit a-law 8khz sound files	 used  on
-		 the Psion palmtop portable computer.
 
-       .raw	 Raw files (no header).
-		 The  sample  rate,  size  (byte, word, etc), and
-		 style (signed, unsigned, etc.)	  of  the  sample
-		 file  must  be	 given.	  The  number of channels
-		 defaults to 1.
+     .wav      Microsoft .WAV RIFF files.
+	       These appear to be very similar to IFF files,  but
+	       not  the	same. They are the native sound	file for-
+	       mat of Windows.	(Obviously, Windows was	 of  such
+	       incredible  importance  to  the	computer industry
+	       that it just had	to have	its own	sound  file  for-
+	       mat.)   Normally	 .wav  files  have all formatting
+	       information in their headers, and so do	not  need
+	       any format options specified for	an input file. If
+	       any are,	they will override the file  header,  and
+	       you will	be warned to this effect.  You had better
+	       know what you are  doing!  Output  format  options
+	       will  cause a format conversion,	and the	.wav will
+	       written appropriately.  Note that it  is	 possible
+	       to  write  data of a type that cannot be	specified
+	       by the .wav header, and you will	 be  warned  that
+	       you a writing a bad file	!  Sox currently can read
+	       PCM, ULAW, ALAW,	MS ADPCM, and IMA (or DVI) ADPCM.
+	       It  can	output	all  of	 these formats except the
+	       ADPCM styles.
 
-       .ub, .sb, .uw, .sw, .ul
-		 These are several  suffices  which  serve  as	a
-		 shorthand  for	 raw  files with a given size and
-		 style.	 Thus, ub, sb, uw, sw, and ul  correspond
-		 to  "unsigned	byte",	"signed	 byte", "unsigned
-		 word", "signed word", and  "ulaw"  (byte).   The
-		 sample	 rate  defaults to 8000 hz if not explic-
-		 itly set, and the number of channels (as always)
-		 defaults  to 1.  There are lots of Sparc samples
-		 floating around in u-law format with  no  header
-		 and fixed at a sample rate of 8000 hz.	 (Certain
-		 sound management software cheerfully ignores the
-		 headers.)   Similarly,	 most Mac sound files are
-		 in unsigned byte format with a	 sample	 rate  of
-		 11025 or 22050 hz.
+     .wve      Psion 8-bit alaw
+	       These are 8-bit a-law 8khz sound	files used on the
+	       Psion palmtop portable computer.
 
-       .auto	 This  is  a  ``meta-type'': specifying this type
-		 for an input file triggers some code that  tries
-		 to  guess  the	 real  type  by looking for magic
-		 words in the  header.	 If  the  type	can't  be
+     .raw      Raw files (no header).
+	       The sample rate,	size (byte, word, etc),	and style
+	       (signed,	 unsigned, etc.)  of the sample	file must
+	       be given.  The number of	channels defaults to 1.
 
+     .ub, .sb, .uw, .sw, .ul
+	       These are several suffices which	serve as a short-
+	       hand  for  raw  files with a given size and style.
+	       Thus,  ub,  sb,	uw,  sw,  and  ul  correspond  to
+	       "unsigned  byte",  "signed byte", "unsigned word",
+	       "signed word", and "ulaw" (byte).  The sample rate
+	       defaults	to 8000	hz if not explicitly set, and the
+	       number of channels  (as	always)	 defaults  to  1.
+	       There are lots of Sparc samples floating	around in
+	       u-law format with no header and fixed at	a  sample
+	       rate   of  8000	hz.   (Certain	sound  management
+	       software	cheerfully ignores the	headers.)   Simi-
+	       larly,  most  Mac sound files are in unsigned byte
+	       format with a sample rate of 11025 or 22050 hz.
 
+     .auto     This is a ``meta-type'':	specifying this	type  for
+	       an  input  file	triggers  some code that tries to
+	       guess the real type by looking for magic	words  in
+	       the  header.   If  the  type can't be guessed, the
+	       program exits with an error  message.   The  input
+	       must be a plain file, not a pipe.  This type can't
+	       be used for output files.
 
-			  June 28, 1999				7
 
 
+SunOS 5.6	  Last change: November	8, 1999			7
 
 
 
-SoX(1)							   SoX(1)
 
 
-		 guessed,  the	program	 exits with an error mes-
-		 sage.	The input must be a  plain  file,  not	a
-		 pipe.	This type can't be used for output files.
 
+User Commands						   SoX(1)
+
+
+
 EFFECTS
-       Only one effect from the palette may be applied to a sound
-       sample.	 To do multiple effects you'll need to run sox in
-       a pipeline.
+     Only one effect from the palette may be applied to	 a  sound
+     sample.   To do multiple effects you'll need to run sox in	a
+     pipeline.
 
-       avg [ -l | -r ]
-		 Reduce the number of channels by  averaging  the
-		 samples,  or  duplicate channels to increase the
-		 number of channels.  This  effect  is	automati-
-		 cally used when the number of input samples dif-
-		 fer then the number of	 output	 channels.   When
-		 reducing  the	number of channels it is possible
-		 to manually specify the avg effect and	 use  the
-		 -l  and  -r  options  to select only the left or
-		 right channel for the output instead of  averag-
-		 ing the two channels.
+     avg [ -l |	-r ]
+	       Reduce the number of  channels  by  averaging  the
+	       samples,	 or  duplicate	channels  to increase the
+	       number of channels.  This effect	is  automatically
+	       used  when the number of	input samples differ then
+	       the number of output channels.  When reducing  the
+	       number  of  channels  it	 is  possible to manually
+	       specify the avg effect  and  use	 the  -l  and  -r
+	       options	to  select only	the left or right channel
+	       for the output instead of averaging the two  chan-
+	       nels.
 
-       band [ -n ] center [ width ]
-		 Apply	 a   band-pass	 filter.   The	frequency
-		 response drops logarithmically around the center
-		 frequency.   The  width  gives	 the slope of the
-		 drop.	The frequencies at  center  +  width  and
-		 center	 -  width  will be half of their original
-		 amplitudes.  Band defaults to a mode oriented to
-		 pitched signals, i.e. voice, singing, or instru-
-		 mental music.	The -n (for  noise)  option  uses
-		 the alternate mode for un-pitched signals.  Band
-		 introduces noise in the  shape	 of  the  filter,
-		 i.e.  peaking	at  the center frequency and set-
-		 tling around it.
+     band [ -n ] center	[ width	]
+	       Apply a band-pass filter.  The frequency	 response
+	       drops logarithmically around the	center frequency.
+	       The width gives the slope of the	drop.	The  fre-
+	       quencies	at center + width and center - width will
+	       be  half	 of  their  original  amplitudes.    Band
+	       defaults	 to  a	mode oriented to pitched signals,
+	       i.e. voice, singing, or instrumental  music.   The
+	       -n  (for	noise) option uses the alternate mode for
+	       un-pitched  signals.   Warning:	-n  introduces	a
+	       power-gain  of about 11dB in the	filter,	so beware
+	       of output clipping.  Band introduces noise in  the
+	       shape  of  the  filter, i.e. peaking at the center
+	       frequency and settling around it.  See filter  for
+	       a bandpass effect with steeper shoulders.
 
-       chorus gain-in gain-out delay decay speed deptch
+     chorus gain-in gain-out delay decay speed deptch
 
-	      -s | -t [ delay decay speed depth -s | -t ... ]
-		 Add a chorus to a sound sample.  Each	quadtuple
-		 delay/decay/speed/depth  gives the delay in mil-
-		 liseconds and the decay  (relative  to	 gain-in)
-		 with  a  modulation  speed  in Hz using depth in
-		 milliseconds.	The modulation is either sinodial
-		 (-s) or triangular (-t).  Gain-out is the volume
-		 of the output.
+	    -s | -t [ delay decay speed	depth -s | -t ... ]
+	       Add a chorus to a sound	sample.	  Each	quadtuple
+	       delay/decay/speed/depth	gives  the  delay in mil-
+	       liseconds and the decay (relative to gain-in) with
+	       a  modulation  speed  in	 Hz  using  depth in mil-
+	       liseconds.  The modulation is either sinodial (-s)
+	       or triangular (-t).  Gain-out is	the volume of the
+	       output.
 
-       compand attack1,decay1[,attack2,decay2...]
+     compand attack1,decay1[,attack2,decay2...]
 
-	       in-dB1,out-dB1[,in-dB2,out-dB2...]
+	     in-dB1,out-dB1[,in-dB2,out-dB2...]
 
-	       [gain] [initial-volume]
-		 Compand (compress or expand) the  dynamic  range
-		 of  a sample.	The attack and decay time specify
-		 the integration time  over  which  the	 absolute
+	     [gain] [initial-volume]
+	       Compand (compress or expand) the	dynamic	range  of
+	       a  sample.   The	attack and decay time specify the
+	       integration time	over which the absolute	value  of
 
 
 
-			  June 28, 1999				8
+SunOS 5.6	  Last change: November	8, 1999			8
 
 
 
 
 
-SoX(1)							   SoX(1)
 
+User Commands						   SoX(1)
 
-		 value	of  the	 input	signal	is  integrated to
-		 determine its volume.	Where more than one  pair
-		 of  attack/decay  parameters are specified, each
-		 channel is treated separately and the number  of
-		 pairs	must agree with the number of input chan-
-		 nels.	The second parameter is a list of  points
-		 on  the  compander's transfer function specified
-		 in dB relative to the	maximum	 possible  signal
-		 amplitude.   The  input  values  must	be  in	a
-		 strictly increasing order but the transfer func-
-		 tion  does  not have to be monotonically rising.
-		 The special value -inf may be used  to	 indicate
-		 that  the input volume should be associated out-
-		 put volume.  The points -inf,-inf  and	 0,0  are
-		 assumed;  the	latter may be overridden, but the
-		 former may not.  The third (optional)	parameter
-		 is  a postprocessing gain in dB which is applied
-		 after	the  compression  has  taken  place;  the
-		 fourth (optional) parameter is an initial volume
-		 to be assumed for each channel when  the  effect
-		 starts.  This permits the user to supply a nomi-
-		 nal level initially, so  that,	 for  example,	a
-		 very large gain is not applied to initial signal
-		 levels before the companding action has begun to
-		 operate:  it  is  quite probable that in such an
-		 event, the  output  would  be	severely  clipped
-		 while	 the   compander  gain	properly  adjusts
-		 itself.
 
-       copy	 Copy the input file to the output file.  This is
-		 the  default  effect if both files have the same
-		 sampling rate.
 
-       cut loopnumber
-		 Extract loop #N from a sample.
+	       the  input  signal  is integrated to determine its
+	       volume.	Where more than	one pair of  attack/decay
+	       parameters  are specified, each channel is treated
+	       separately and the number of pairs must agree with
+	       the  number of input channels.  The second parame-
+	       ter  is	a  list	 of  points  on	 the  compander's
+	       transfer	 function specified in dB relative to the
+	       maximum	possible  signal  amplitude.   The  input
+	       values  must be in a strictly increasing	order but
+	       the transfer function does not have to be monoton-
+	       ically rising.  The special value -inf may be used
+	       to indicate that	the input volume should	be  asso-
+	       ciated  output  volume.	 The points -inf,-inf and
+	       0,0 are assumed;	the latter may be overridden, but
+	       the  former may not.  The third (optional) parame-
+	       ter is  a  postprocessing  gain	in  dB	which  is
+	       applied after the compression has taken place; the
+	       fourth (optional) parameter is an  initial  volume
+	       to  be  assumed	for  each channel when the effect
+	       starts.	This permits the user to supply	a nominal
+	       level  initially,  so  that,  for  example, a very
+	       large gain is not applied to initial signal levels
+	       before the companding action has	begun to operate:
+	       it is quite probable that in such  an  event,  the
+	       output  would  be  severely clipped while the com-
+	       pander gain properly adjusts itself.
 
-       deemph	 Apply a treble attenuation  shelving  filter  to
-		 samples  in  audio  cd	 format.   The	frequency
-		 response of pre-emphasized recordings is  recti-
-		 fied.	 The filtering is defined in the standard
-		 document ISO 908.
+     copy      Copy the	input file to the output file.	 This  is
+	       the  default  effect  if	 both files have the same
+	       sampling	rate.
 
-       echo gain-in gain-out delay decay [ delay decay ... ]
-		 Add echoing to a sound sample.	 Each delay/decay
-		 part  gives  the  delay  in milliseconds and the
-		 decay (relative to gain-in) of that echo.  Gain-
-		 out is the volume of the output.
+     cut loopnumber
+	       Extract loop #N from a sample.
 
-       echos gain-in gain-out delay decay [ delay decay ... ]
-		 Add a sequence of echos to a sound sample.  Each
-		 delay/decay part gives the delay in milliseconds
-		 and  the  decay  (relative  to	 gain-in) of that
-		 echo.	Gain-out is the volume of the output.
+     deemph    Apply a treble attenuation shelving filter to sam-
+	       ples  in	 audio cd format.  The frequency response
+	       of pre-emphasized recordings  is	 rectified.   The
+	       filtering  is defined in	the standard document ISO
+	       908.
 
+     echo gain-in gain-out delay decay [ delay decay ... ]
+	       Add echoing to a	sound sample.	Each  delay/decay
+	       part gives the delay in milliseconds and	the decay
+	       (relative to gain-in) of	that echo.   Gain-out  is
+	       the volume of the output.
 
+     echos gain-in gain-out delay decay	[ delay	decay ... ]
+	       Add a sequence of echos to a sound  sample.   Each
+	       delay/decay  part  gives	the delay in milliseconds
+	       and the decay (relative to gain-in) of that  echo.
+	       Gain-out	is the volume of the output.
 
 
-			  June 28, 1999				9
 
 
+SunOS 5.6	  Last change: November	8, 1999			9
 
 
 
-SoX(1)							   SoX(1)
 
 
-       flanger gain-in gain-out delay decay speed -s | -t
-		 Add a flanger to a sound  sample.   Each  triple
-		 delay/decay/speed  gives  the delay in millisec-
-		 onds and the decay (relative to gain-in) with	a
-		 modulation  speed  in	Hz.   The  modulation  is
-		 either sinodial (-s) or triangular (-t).   Gain-
-		 out is the volume of the output.
 
-       highp center
-		 Apply	 a   high-pass	 filter.   The	frequency
-		 response drops logarithmically with center  fre-
-		 quency	 in the middle of the drop.  The slope of
-		 the filter is quite gentle.
+User Commands						   SoX(1)
 
-       lowp center
-		 Apply a low-pass filter.  The frequency response
-		 drops	logarithmically	 with center frequency in
-		 the middle of the drop.  The slope of the filter
-		 is quite gentle.
 
-       map	 Display a list of loops in a sample, and miscel-
-		 laneous loop info.
 
-       mask	 Add "masking  noise"  to  signal.   This  effect
-		 deliberately  adds  white  noise  to  a sound in
-		 order to mask quantization effects,  created  by
-		 the  process  of  playing a sound digitally.  It
-		 tends to mask buzzing voices, for  example.   It
-		 adds  1/2  bit of noise to the sound file at the
-		 output bit depth.
+     filter [ low ]-[ high ] [ window-len [ beta ] ]
+	       Apply  a	 Sinc-windowed	lowpass,   highpass,   or
+	       bandpass	filter of given	window length to the sig-
+	       nal.  low refers	to the frequency of the	lower 6dB
+	       corner  of  the	filter.	  high refers to the fre-
+	       quency of the upper 6dB corner of the filter.
 
-       phaser gain-in gain-out delay decay speed -s | -t
-		 Add a phaser to a  sound  sample.   Each  triple
-		 delay/decay/speed  gives  the delay in millisec-
-		 onds and the decay (relative to gain-in) with	a
-		 modulation  speed  in	Hz.   The  modulation  is
-		 either sinodial (-s) or  triangular  (-t).   The
-		 decay should be less than 0.5 to avoid feedback.
-		 Gain-out is the volume of the output.
+	       A  lowpass  filter  is  obtained	 by  leaving  low
+	       unspecified,  or	0.  A highpass filter is obtained
+	       by leaving high unspecified, or 0, or greater than
+	       or equal	to the Nyquist freq.
 
-       pick	 Select the left or right  channel  of	a  stereo
-		 sample,  or  one  of  four channels in a quadro-
-		 phonic sample.
+	       The window-len, if unspecified, defaults	 to  128.
+	       Longer windows give a sharper cutoff, smaller win-
+	       dows a more gradual cutoff.
 
-       polyphase [ -w < num / ham > ]
+	       The beta, if unspecified, defaults  to  16.   This
+	       selects a Kaiser	window.	 You can select	a Nuttall
+	       window by specifying anything <=	 2.0  here.   For
+	       more  discussion	 of beta, look under the resample
+	       effect.
 
-		 [  -width <  long  / short  / # > ]
 
-		 [ -cutoff #  ]
-		 Translate input sampling rate to output sampling
-		 rate  via  polyphase  interpolation, a DSP algo-
-		 rithm.	 This method is slow  and  uses	 lots  of
-		 RAM, but gives much better results then rate.
-		 -w  <	nut / ham > : select either a Nuttal (~90
+     flanger gain-in gain-out delay decay speed	-s | -t
+	       Add a flanger to	 a  sound  sample.   Each  triple
+	       delay/decay/speed  gives	the delay in milliseconds
+	       and the decay (relative to gain-in) with	a modula-
+	       tion  speed in Hz.  The modulation is either sino-
+	       dial (-s) or triangular	(-t).	Gain-out  is  the
+	       volume of the output.
 
+     highp center
+	       Apply a high-pass filter.  The frequency	 response
+	       drops logarithmically with center frequency in the
+	       middle of the drop.  The	slope of  the  filter  is
+	       quite  gentle.	See  filter for	a highpass effect
+	       with sharper cutoff.
 
+     lowp center
+	       Apply a low-pass	filter.	 The  frequency	 response
+	       drops logarithmically with center frequency in the
+	       middle of the drop.  The	slope of  the  filter  is
+	       quite  gentle.	See  filter  for a lowpass effect
+	       with sharper cutoff.
 
-			  June 28, 1999			       10
+     map       Display a list of loops in a sample,  and  miscel-
+	       laneous loop info.
 
+     mask      Add "masking noise" to signal.  This effect  deli-
+	       berately	 adds  white noise to a	sound in order to
+	       mask quantization effects, created by the  process
+	       of  playing  a  sound digitally.	 It tends to mask
 
 
 
+SunOS 5.6	  Last change: November	8, 1999		       10
 
-SoX(1)							   SoX(1)
 
 
-		 dB stopband) or Hamming (~43 dB  stopband)  win-
-		 dow.  Warning: Nuttall windows require 2x length
-		 than Hamming windows.	Default is nut.
-		 -width long / short / # : specify the	width  of
-		 the  filter.  long is 1024 samples; short is 128
-		 samples.  Alternatively, an exact number can  be
-		 used.	Default is long.
-		 -cutoff  # : specify the filter cutoff frequency
-		 in terms of fraction of  bandwidth.   If  upsam-
-		 pling,	 then this is the fraction of the orignal
-		 signal that should go through.	 If downsampling,
-		 this  is  the	fraction of the signal left after
-		 downsampling.	Default is 0.95.   Remember  that
-		 this is a float.
 
 
-       rate	 Translate input sampling rate to output sampling
-		 rate via linear interpolation to the Least  Com-
-		 mon Multiple of the two sampling rates.  This is
-		 the default effect if the two files have differ-
-		 ent  sampling	rates and the preview options was
-		 specified.  This is fast but noisy: the spectrum
-		 of  the  original  sound will be shifted upwards
-		 and duplicated faintly when up-translating by	a
-		 multiple.   Lerp-ing  is  acceptable  for  cheap
-		 8-bit sound hardware, but for	CD-quality  sound
-		 you   should  instead	use  either  resample  or
-		 polyphase.  If you are wondering which of  Sox's
-		 rate  changing	 effects to ues, you will want to
-		 read a detailed  analysis  of	all  of	 them  at
-		 http://eakaw2.et.tu-dresden.de/~andreas/resam-
-		 ple/resample.html
 
-       resample [ rolloff [ beta ] ]
-		 Translate input sampling rate to output sampling
-		 rate  via  simulated  analog  filtration.   This
-		 method is slower than rate, but gives much  bet-
-		 ter results.  rolloff refers to the cut-off fre-
-		 quency of the low pass filter and  is	given  in
-		 terms	of  the	 Nyquist  frequency for the lower
-		 sample rate.  rolloff therefor should	be  some-
-		 thing	between	 0. and 1., in practice 0.8-0.95.
-		 beta trades stop band rejection against  transi-
-		 tion  width  from passband to stop band.  Larger
-		 beta means a slower transition and greater stop-
-		 band rejection.  beta should be at least greater
-		 than 2.  The default is rollof 0.8,  beta  17.5,
-		 which	is  rather  conservative  with respect to
-		 aliasing.  Lower beta and higher rolloff  values
-		 preserve  more high frequency signal energy, but
-		 introduce measurable  artifacts.   This  is  the
-		 default  effect  if the two files have different
-		 sampling rates.
+User Commands						   SoX(1)
 
 
 
+	       buzzing voices, for example.  It	adds 1/2  bit  of
+	       noise to	the sound file at the output bit depth.
 
-			  June 28, 1999			       11
+     phaser gain-in gain-out delay decay speed -s | -t
+	       Add a phaser  to	 a  sound  sample.   Each  triple
+	       delay/decay/speed  gives	the delay in milliseconds
+	       and the decay (relative to gain-in) with	a modula-
+	       tion  speed in Hz.  The modulation is either sino-
+	       dial (-s) or triangular (-t).  The decay	should be
+	       less  than 0.5 to avoid feedback.  Gain-out is the
+	       volume of the output.
 
+     pick      Select the left or right	channel	of a stereo  sam-
+	       ple,  or	 one  of  four channels	in a quadrophonic
+	       sample.
 
+     polyphase [ -w < num / ham	> ]
 
+	       [  -width <  long  / short  / # > ]
 
+	       [ -cutoff #  ]
+	       Translate input sampling	rate to	 output	 sampling
+	       rate via	polyphase interpolation, a DSP algorithm.
+	       This method is slow and	uses  lots  of	RAM,  but
+	       gives much better results then rate.
+	       -w < nut	/ ham >	: select either	a Nuttal (~90  dB
+	       stopband)  or  Hamming  (~43  dB	stopband) window.
+	       Warning:	Nuttall	windows	require	 2x  length  than
+	       Hamming windows.	 Default is nut.
+	       -width long / short / # : specify the width of the
+	       filter.	 long  is 1024 samples;	short is 128 sam-
+	       ples.  Alternatively, an	exact number can be used.
+	       Default is long.
+	       -cutoff # : specify the filter cutoff frequency in
+	       terms  of  fraction  of bandwidth.  If upsampling,
+	       then this is the	fraction of  the  orignal  signal
+	       that  should go through.	 If downsampling, this is
+	       the fraction of the  signal  left  after	 downsam-
+	       pling.	Default	is 0.95.  Remember that	this is	a
+	       float.
 
-SoX(1)							   SoX(1)
 
+     rate      Translate input sampling	rate to	 output	 sampling
+	       rate  via linear	interpolation to the Least Common
+	       Multiple	of the two sampling rates.  This  is  the
+	       default	effect	if  the	 two files have	different
+	       sampling	rates and the preview options was  speci-
+	       fied.   This  is	 fast but noisy:  the spectrum of
+	       the original sound will	be  shifted  upwards  and
+	       duplicated faintly when up-translating by a multi-
+	       ple.  Lerp-ing is acceptable for	cheap 8-bit sound
+	       hardware,  but  for  CD-quality	sound  you should
 
-       reverb gain-out delay [ delay ... ]
-		 Add reverbation to a sound sample.   Each  delay
-		 is  given  in	milliseconds  and its feedback is
-		 depending on the  reverb-time	in  milliseconds.
-		 Each  delay  should  be  in the range of half to
-		 quarter of reverb-time to get a realistic rever-
-		 bation.  Gain-out is the volume of the output.
 
-       reverse	 Reverse  the  sound sample completely.	 Included
-		 for finding Satanic subliminals.
 
-       split	 Turn a mono sample into a stereo sample by copy-
-		 ing  the  input  channel  to  the left and right
-		 channels.
+SunOS 5.6	  Last change: November	8, 1999		       11
 
-       stat [ debug | -v ]
-		 Do a statistical check on the	input  file,  and
-		 print	results on the standard error file.  stat
-		 may copy the file untouched from input	 to  out-
-		 put,  if you select an output file.  The "Volume
-		 Adjustment:" field in the statistics  gives  you
-		 the  argument	to  the -v number which will make
-		 the sample as loud as possible without clipping.
-		 There	is  an	optional  parameter  -v that will
-		 print out the "Volume Adjustment:" field's value
-		 and  return.  This could be of use in scripts to
-		 auto convert the volume.  There is  an	 also  an
-		 optional  parameter  debug  that  will place sox
-		 into debug mode and print out a hex dump of  the
-		 sound	file  from the internal buffer that is in
-		 32-bit signed PCM data.  This is mainly only  of
-		 use  in tracking down endian problems that creep
-		 in to sox on cross-platform versions.
 
-       swap [ 1 2 3 4 ]
-		 Swap channels in multi-channel sound files.   In
-		 files	with more than 2 channels you may specify
-		 the order that the channels should be rearranged
-		 in.
 
-       vibro speed  [ depth ]
-		 Add  the  world-famous	 Fender Vibro-Champ sound
-		 effect to a sound sample by using a sine wave as
-		 the volume knob.  Speed gives the Hertz value of
-		 the wave.  This must be under 30.   Depth  gives
-		 the  amount  the  volume is cut into by the sine
-		 wave, ranging 0.0 to 1.0 and defaulting to  0.5.
 
-       Sox  enforces certain effects.  If the two files have dif-
-       ferent sampling rates, the requested effect must be one of
-       copy,  or rate, If the two files have different numbers of
-       channels, the avg effect must be requested.
 
 
+User Commands						   SoX(1)
 
 
 
-			  June 28, 1999			       12
+	       instead use either resample or polyphase.  If  you
+	       are wondering which of Sox's rate changing effects
+	       to ues, you will	want to	read a detailed	 analysis
+	       of    all    of	 them	at   http://eakaw2.et.tu-
+	       dresden.de/~andreas/resample/resample.html
+	       [Nov,1999:  These  tests	 need  to  be updated for
+	       sox-12.18, which	has bugfixes to	the resample  and
+	       polyphase code.]
 
+     resample [	-qs | -q | -ql ] [ rolloff [ beta ] ]
+	       Translate input sampling	rate to	 output	 sampling
+	       rate via	simulated analog filtration.  This method
+	       is  slower  than	 rate,	but  gives  much   better
+	       results.
 
+	       The -qs,	-q,  or	 -ql  options  specify	increased
+	       accuracy	at the cost of lower execution speed.  By
+	       default,	linear interpolation is	used, with a win-
+	       dow  width  about  37  samples  at the lower rate.
+	       This gives an  accuracy	of  about  16  bits,  but
+	       insufficient  stopband  rejection in the	case that
+	       you want	to have	rolloff	greater	than  about  0.85
+	       of  the	Nyquist	 frequency.   The -q* options use
+	       quadratic interpolation	of  filter  coefficients,
+	       resulting in about 22 bits precision.  -qs, -q, or
+	       -ql use window lengths of 37, 75, or 150	 samples,
+	       respectively,  at the lower sample-rate of the two
+	       files.  This means progressively	sharper	stop-band
+	       rejection,   at	proportionally	slower	execution
+	       times.
 
+	       rolloff refers to the cut-off frequency of the low
+	       pass  filter  and is given in terms of the Nyquist
+	       frequency for  the  lower  sample  rate.	  rolloff
+	       therefore  should  be something between 0. and 1.,
+	       in practice 0.8-0.95.  The default is 0.8.
 
+	       The beta	parameter determines the type  of  filter
+	       window  used.   Any  value greater than 2.0 is the
+	       beta for	a Kaiser window.  Beta <= 2.0  selects	a
+	       Nuttall	window.	 If unspecified, the default is	a
+	       Kaiser window with beta 16.
 
-SoX(1)							   SoX(1)
+	       In the case of Kaiser window  beta  >  2.0,  lower
+	       betas  produce  a  somewhat faster transition from
+	       passband	to stopband, 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
+	       cutoff,	don't use low beta's, use a longer sample
+	       window.	A Nuttall window is selected by	 specify-
+	       ing  any	 'beta'	 <= 2, and the Nuttall window has
+	       somewhat	steeper	cutoff than  the  default  Kaiser
 
 
-BUGS
-       The syntax is horrific.	It's very tempting to  include	a
-       default	system	that allows an effect name as the program
-       name and just pipes a sound sample from standard input  to
-       standard	 output,  but the problem of inputting the sample
-       rates makes this unworkable.
 
-       Please report any bugs found in this  version  of  sox  to
-       Chris Bagwell (cbagwell@sprynet.com)
+SunOS 5.6	  Last change: November	8, 1999		       12
 
-FILES
-SEE ALSO
-       play(1), rec(1)
 
-NOTICES
-       The   echoplex  effect  is:  Copyright  (C)  1989  by  Jef
-       Poskanzer.
 
-       Permission to use, copy, modify, and distribute this soft-
-       ware and its documentation for any purpose and without fee
-       is hereby  granted,  provided  that  the	 above	copyright
-       notice  appear  in all copies and that both that copyright
-       notice and this permission  notice  appear  in  supporting
-       documentation.	This software is provided "as is" without
-       express or implied warranty.
 
-       The version of Sox that accompanies this	 manual	 page  is
-       support	by  Chris Bagwell (cbagwell@sprynet.com).  Please
-       refer any questions regarding it to this address.  You may
-       obtain	the   latest   version	 at   the  the	web  site
-       http://home.sprynet.com/~cbagwell/sox.html
 
 
+User Commands						   SoX(1)
 
 
 
+	       window.	 You  will  probably  not need to use the
+	       beta parameter at all, unless you are just curious
+	       about  comparing	the effects of Nuttall vs. Kaiser
+	       windows.
 
+	       This is the default effect if the two  files  have
+	       different  sampling rates.  Default parameters are
+	       Kaiser window of	length 37, rolloff 0.80, beta 16,
+	       linear	interpolation.	  -qs  is  only	 slightly
+	       slower, but more	accurate  for  16-bit  or  higher
+	       precision.
 
 
+     reverb gain-out delay [ delay ... ]
+	       Add reverbation to a sound sample.  Each	delay  is
+	       given  in milliseconds and its feedback is depend-
+	       ing on  the  reverb-time	 in  milliseconds.   Each
+	       delay should be in the range of half to quarter of
+	       reverb-time  to	get  a	 realistic   reverbation.
+	       Gain-out	is the volume of the output.
 
+     reverse   Reverse the sound sample	completely.  Included for
+	       finding Satanic subliminals.
 
+     split     Turn a mono sample into a stereo	sample by copying
+	       the input channel to the	left and right channels.
 
+     stat [ debug | -v ]
+	       Do a statistical	check  on  the	input  file,  and
+	       print  results  on  the standard	error file.  stat
+	       may copy	the file untouched from	input to  output,
+	       if  you select an output	file. The "Volume Adjust-
+	       ment:" field in the statistics gives you	the argu-
+	       ment  to	 the -v	number which will make the sample
+	       as loud as possible without clipping. There is  an
+	       optional	 parameter  -v	that  will  print out the
+	       "Volume Adjustment:"  field's  value  and  return.
+	       This  could  be	of use in scripts to auto convert
+	       the volume.  There is an	also an	optional  parame-
+	       ter  debug that will place sox into debug mode and
+	       print out a hex dump of the sound  file	from  the
+	       internal	buffer that is in 32-bit signed	PCM data.
+	       This is mainly only of use in tracking down endian
+	       problems	 that  creep  in to sox	on cross-platform
+	       versions.
 
+     swap [ 1 2	3 4 ]
+	       Swap channels in	multi-channel  sound  files.   In
+	       files  with  more  than 2 channels you may specify
+	       the order that the channels should  be  rearranged
+	       in.
 
 
 
 
+SunOS 5.6	  Last change: November	8, 1999		       13
 
 
 
@@ -849,10 +859,66 @@
 
 
 
+User Commands						   SoX(1)
 
 
 
+     vibro speed  [ depth ]
+	       Add  the	 world-famous  Fender  Vibro-Champ  sound
+	       effect  to  a sound sample by using a sine wave as
+	       the volume knob.	 Speed gives the Hertz	value  of
+	       the wave.  This must be under 30.  Depth	gives the
+	       amount the volume is cut	into by	 the  sine  wave,
+	       ranging 0.0 to 1.0 and defaulting to 0.5.
 
-			  June 28, 1999			       13
+     Sox enforces certain effects.  If the two	files  have  dif-
+     ferent  sampling  rates, the requested effect must	be one of
+     copy, or rate, If the two files have  different  numbers  of
+     channels, the avg effect must be requested.
+
+BUGS
+     The syntax	is horrific.  It's very	 tempting  to  include	a
+     default  system  that  allows  an effect name as the program
+     name and just pipes a sound sample	from  standard	input  to
+     standard  output,	but  the  problem of inputting the sample
+     rates makes this unworkable.
+
+     Please report any bugs found in this version of sox to Chris
+     Bagwell (cbagwell@sprynet.com)
+
+FILES
+SEE ALSO
+     play(1), rec(1)
+
+NOTICES
+     The  echoplex  effect  is:	  Copyright  (C)  1989	 by   Jef
+     Poskanzer.
+
+     Permission	 to  use,  copy,  modify,  and	distribute   this
+     software  and  its	documentation for any purpose and without
+     fee is hereby granted, provided  that  the	 above	copyright
+     notice  appear  in	 all  copies and that both that	copyright
+     notice and	this permission	notice appear in supporting docu-
+     mentation.	  This	software  is  provided	"as  is"  without
+     express or	implied	warranty.
+
+     The version of Sox	that accompanies this manual page is sup-
+     port  by Chris Bagwell (cbagwell@sprynet.com).  Please refer
+     any questions regarding it	to this	address.  You may  obtain
+     the     latest    version	  at	the    the    web    site
+     http://home.sprynet.com/~cbagwell/sox.html
+
+
+
+
+
+
+
+
+
+
+
+SunOS 5.6	  Last change: November	8, 1999		       14
+
 
 
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -43,11 +43,11 @@
 
 FSRC	= 8svx.c aiff.c au.c auto.c avr.c cdr.c cvsd.c dat.c g721.c \
 	  g723_24.c g723_40.c g72x.c gsm.c hcom.c maud.c raw.c \
-	  sbdsp.c sf.c smp.c sndrtool.c tx16w.c voc.c wav.c wve.c
+	  sf.c smp.c sndrtool.c tx16w.c voc.c wav.c wve.c
 
 ESRC	= avg.c band.c bandpass.c breject.c btrworth.c chorus.c compand.c \
-	  copy.c cut.c deemphas.c dyn.c echo.c echos.c flanger.c highp.c \
-	  highpass.c lowp.c lowpass.c map.c mask.c phaser.c pick.c \
+	  copy.c cut.c deemphas.c dyn.c echo.c echos.c filter.c flanger.c \
+	  highp.c highpass.c lowp.c lowpass.c map.c mask.c phaser.c pick.c \
 	  polyphas.c rate.c resample.c reverb.c reverse.c split.c \
 	  stat.c swap.c vibro.c 
 
@@ -65,11 +65,11 @@
 
 FOBJ	= 8svx.o aiff.o au.o auto.o avr.o cdr.o cvsd.o dat.o g721.o \
 	  g723_24.o g723_40.o g72x.o gsm.o hcom.o maud.o raw.o \
-	  sbdsp.o sf.o smp.o sndrtool.o tx16w.o voc.o wav.o wve.o
+	  sf.o smp.o sndrtool.o tx16w.o voc.o wav.o wve.o
 
 EOBJ	= avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
-	  copy.o cut.o deemphas.o dyn.o echo.o echos.o flanger.o highp.o \
-	  highpass.o lowp.o lowpass.o map.o mask.o phaser.o pick.o \
+	  copy.o cut.o deemphas.o dyn.o echo.o echos.o filter.o flanger.o \
+	  highp.o highpass.o lowp.o lowpass.o map.o mask.o phaser.o pick.o \
 	  polyphas.o rate.o resample.o reverb.o reverse.o split.o \
 	  stat.o swap.o vibro.o
 
--- /dev/null
+++ b/src/filter.c
@@ -1,0 +1,289 @@
+/*
+ * Windowed sinc lowpass/bandpass/highpass filter.
+ */
+
+/*
+ * November 7, 1999
+ *
+ * This source code 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.
+ *
+ */
+
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "st.h"
+
+#ifndef HAVE_MEMMOVE
+#define memmove(dest,src,len) bcopy((src),(dest),(len))
+#endif
+
+#define Float double/*float*/
+
+#define ISCALE 0x10000
+#define BUFFSIZE 8192
+
+/* Private data for Lerp via LCM file */
+typedef struct filterstuff {
+	LONG rate;
+	LONG freq0;										/* low  corner freq */
+	LONG freq1;										/* high corner freq */
+	double rolloff;								/* roll-off frequency */
+	double beta;   								/* >2 is kaiser window beta, <=2 selects nuttall window */
+	LONG Nwin;
+	Float *Fp;										/* [Xh+1] Filter coefficients */
+	LONG Xh;											/* number of past/future samples needed by filter  */
+	LONG Xt;											/* target to enter new data into X */
+	Float *X, *Y;									/* I/O buffers */
+} *filter_t;
+
+extern int 
+makeFilter(P5(Float Fp[], LONG Nwing, double Froll, double Beta, LONG Num));
+
+static void FiltWin(P2(filter_t f, LONG Nx));
+
+/*
+ * Process options
+ */
+void filter_getopts(effp, n, argv)
+eff_t effp;
+int n;
+char **argv;
+{
+	filter_t f = (filter_t) effp->priv;
+
+	f->beta = 16;  /* Kaiser window, beta 16 */
+	f->Nwin = 128;
+	
+	f->freq0 = f->freq1 = 0;
+	if (n >= 1) {
+		char *p;
+		p = argv[0];
+		if (*p != '-')
+			f->freq1 = strtol(p, &p, 10);
+		if (*p == '-') {
+			f->freq0 = f->freq1;
+			f->freq1 = strtol(p+1, &p, 10);
+		}
+		if (*p) f->freq1 = f->freq0 = 0;
+	}
+	/* fprintf(stderr,"freq: %d-%d\n", f->freq0, f->freq1);fflush(stderr); */
+	if (f->freq0 == 0 && f->freq1 == 0)
+		fail("Usage: filter low-high [ windowlength [ beta ] ]");
+
+	if ((n >= 2) && !sscanf(argv[1], "%ld", &f->Nwin))
+		fail("Usage: filter low-high [ windowlength ]");
+	else if (f->Nwin < 4) {
+		fail("filter: window length (%ld) <4 is too short", f->Nwin);
+	}
+
+	if ((n >= 3) && !sscanf(argv[2], "%lf", &f->beta))
+		fail("Usage: filter low-high [ windowlength [ beta ] ]");
+
+	report("filter opts: cutoff %f, window-len %d, beta %f\n", f->rolloff, f->Nwin, f->beta);
+}
+
+/*
+ * Prepare processing.
+ */
+void filter_start(effp)
+eff_t effp;
+{
+	filter_t f = (filter_t) effp->priv;
+	Float *Fp0, *Fp1;
+	LONG Xh0, Xh1, Xh;
+	int i;
+
+	f->rate = effp->ininfo.rate;
+
+	if (f->freq1 > f->rate/2 || f->freq1 <= 0)
+		f->freq1 = f->rate/2;
+	if ((f->freq0 < 0) || (f->freq0 > f->freq1))
+		fail("filter: low(%d),high(%d) parameters must satisfy 0 <= low <= high <= %d",
+					f->freq0, f->freq1, f->rate/2);
+	
+	Xh = f->Nwin/2;
+	Fp0 = (Float *) malloc(sizeof(Float) * (Xh + 2)) + 1;
+	if (f->freq0 > f->rate/200) {
+		Xh0 = makeFilter(Fp0, Xh, 2.0*(double)f->freq0/f->rate, f->beta, 1);
+		if (Xh0 <= 1)
+			fail("filter: Unable to make low filter\n");
+	} else {
+		Xh0 = 0;
+	}
+	Fp1 = (Float *) malloc(sizeof(Float) * (Xh + 2)) + 1;
+	/* need Fp[-1] and Fp[Xh] for makeFilter */
+	if (f->freq1 < f->rate/2) {
+		Xh1 = makeFilter(Fp1, Xh, 2.0*(double)f->freq1/f->rate, f->beta, 1);
+		if (Xh1 <= 1)
+			fail("filter: Unable to make high filter\n");
+	} else {
+		Fp1[0] = 1.0;
+		Xh1 = 1;
+	}
+	/* now subtract Fp0[] from Fp1[] */
+	Xh = (Xh0>Xh1)?  Xh0:Xh1;
+	Xh -= 1;
+	for (i=0; i<Xh; i++) {
+		Float 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;
+	f->Nwin = 2*Xh + 1;
+	f->Xh = Xh;
+	f->Xt = Xh;
+
+	f->X = (Float *) malloc(sizeof(Float) * (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;
+}
+
+/*
+ * Processed signed long samples from ibuf to obuf.
+ * Return number of samples processed.
+ */
+
+void filter_flow(effp, ibuf, obuf, isamp, osamp)
+eff_t effp;
+LONG *ibuf, *obuf;
+LONG *isamp, *osamp;
+{
+	filter_t f = (filter_t) effp->priv;
+	LONG i, Nx, Nproc;
+
+	/* constrain amount we actually process */
+	/* fprintf(stderr,"Xh %d, Xt %d, isamp %d, ",f->Xh, f->Xt, *isamp);fflush(stderr); */
+	Nx = BUFFSIZE + 2*f->Xh - f->Xt;
+	if (Nx > *isamp) Nx = *isamp;
+	if (Nx > *osamp) Nx = *osamp;
+	*isamp = Nx;
+
+	{
+		Float *xp, *xtop;
+		xp = f->X + f->Xt;
+		xtop = xp + Nx;
+		if (ibuf != NULL) {
+			while (xp < xtop)
+				*xp++ = (Float)(*ibuf++) / ISCALE;
+		} else {
+			while (xp < xtop)
+				*xp++ = 0;
+		}
+	}
+
+	Nproc = f->Xt + Nx - 2*f->Xh;
+
+	if (Nproc <= 0) {
+		f->Xt += Nx;
+		*osamp = 0;
+		return;
+	}
+	/* fprintf(stderr,"flow Nproc %d\n",Nproc); */
+	FiltWin(f, Nproc);
+
+	/* Copy back portion of input signal that must be re-used */
+	Nx += f->Xt;
+	memmove(f->X, f->X + Nx - 2*f->Xh, sizeof(Float)*2*f->Xh); 
+	f->Xt = 2*f->Xh;
+
+	for (i = 0; i < Nproc; i++)
+		*obuf++ = f->Y[i] * ISCALE;
+
+	*osamp = Nproc;
+}
+
+/*
+ * Process tail of input samples.
+ */
+void filter_drain(effp, obuf, osamp)
+eff_t effp;
+LONG *obuf;
+LONG *osamp;
+{
+	filter_t f = (filter_t) effp->priv;
+	LONG isamp_res, *Obuf, osamp_res;
+
+	/* fprintf(stderr,"Xh %d, Xt %d  <--- DRAIN\n",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) {
+		LONG Isamp, Osamp;
+		Isamp = isamp_res;
+		Osamp = osamp_res;
+		filter_flow(effp, NULL, Obuf, &Isamp, &Osamp);
+	  /* fprintf(stderr,"DRAIN isamp,osamp  (%d,%d) -> (%d,%d)\n",
+		 * isamp_res,osamp_res,Isamp,Osamp); */
+		Obuf += Osamp;
+		osamp_res -= Osamp;
+		isamp_res -= Isamp;
+	};
+	*osamp -= osamp_res;
+	/* fprintf(stderr,"DRAIN osamp %d\n", *osamp); */
+	if (isamp_res)
+		warn("drain overran obuf by %d\n", isamp_res); fflush(stderr);
+}
+
+/*
+ * Do anything required when you stop reading samples.  
+ * Don't close input file! 
+ */
+void filter_stop(effp)
+eff_t effp;
+{
+	filter_t f = (filter_t) effp->priv;
+
+	free(f->Fp - 1);
+	free(f->X);
+}
+
+static double jprod(Fp, Xp, ct)
+const Float Fp[], *Xp;
+LONG ct;
+{
+	const Float *fp, *xp, *xq;
+	double v = 0;
+	
+	fp = Fp + ct;					/* so sum starts with smaller coef's */
+	xp = Xp - ct;
+	xq = Xp + ct;
+	do {
+		v += *fp * (*xp + *xq);
+		xp++; xq--;
+	} while (--fp > Fp);
+	v += *fp * *xp;
+	return v;
+}
+
+static void FiltWin(f, Nx)
+filter_t f;
+LONG Nx;
+{
+	Float *Y;
+	Float *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++;
+	}
+}
--- a/src/g72x.c
+++ b/src/g72x.c
@@ -348,6 +348,7 @@
 				a2p += fa1 >> 5;
 
 			if (pk0 ^ state_ptr->pk[1])
+			{
 				/* LIMC */
 				if (a2p <= -12160)
 					a2p = -12288;
@@ -355,6 +356,7 @@
 					a2p = 12288;
 				else
 					a2p -= 0x80;
+			}
 			else if (a2p <= -12416)
 				a2p = -12288;
 			else if (a2p >= 12160)
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -168,19 +168,6 @@
 
 /* raw prototypes are defined in st.h since they are used globally. */
 
-#if	defined(BLASTER) || defined(SBLAST)
-char *sbdspnames[] = {
-	"sbdsp",
-	(char *) 0
-};
-extern void sbdspstartread();
-extern LONG sbdspread();
-extern void sbdspstopread();
-extern void sbdspstartwrite();
-extern void sbdspwrite();
-extern void sbdspstopwrite();
-#endif
-
 char *sbnames[] = {
 	"sb",
 	(char *) 0
@@ -200,6 +187,14 @@
 	(char *) 0,
 };
 
+char *slnames[] = {
+	"sl",
+	(char *) 0,
+};
+
+extern void slstartread();
+extern void slstartwrite();
+
 extern void smpstartread();
 extern LONG smpread();
 extern void smpwrite();
@@ -375,12 +370,6 @@
 	{rawnames, FILE_STEREO,
 		rawstartread, rawread, rawstopread, 	       /* Raw format */
 		rawstartwrite, rawwrite, rawstopwrite},
-#if	defined(BLASTER) || defined(SBLAST)
-	/* 386 Unix sound blaster player. */
-	{sbdspnames, FILE_STEREO,
-		sbdspstartread, sbdspread, sbdspstopread,      /* /dev/sbdsp */
-		sbdspstartwrite, sbdspwrite, sbdspstopwrite},	
-#endif
 	{sbnames, FILE_STEREO,
 		sbstartread, rawread, rawstopread, 	  /* signed byte raw */
 		sbstartwrite, rawwrite, rawstopwrite},	
@@ -387,6 +376,9 @@
 	{sfnames, FILE_STEREO,
 		sfstartread, rawread, rawstopread,       /* IRCAM Sound File */
 		sfstartwrite, rawwrite, rawstopwrite},
+	{ slnames, FILE_STEREO,
+	    	slstartread, rawread, rawstopread,	/* signed long raw */
+		slstartwrite, rawwrite, rawstopwrite },
 	{smpnames, FILE_STEREO | FILE_LOOPS,
 		smpstartread, smpread, nothing,	       /* SampleVision sound */
 		smpstartwrite, smpwrite, smpstopwrite},	     /* Turtle Beach */
@@ -497,6 +489,12 @@
 extern void echos_drain();
 extern void echos_stop();
 
+extern void filter_getopts();
+extern void filter_start();
+extern void filter_flow();
+extern void filter_drain();
+extern void filter_stop();
+
 extern void flanger_getopts();
 extern void flanger_start();
 extern void flanger_flow();
@@ -629,6 +627,9 @@
 	{"echos", 0, 
 		echos_getopts, echos_start, echos_flow,
 	        echos_drain, echos_stop},
+	{ "filter", 0,
+	    	filter_getopts, filter_start, filter_flow,
+		filter_drain, filter_stop},
 	{"flanger", 0,
 	        flanger_getopts, flanger_start, flanger_flow,
 	        flanger_drain, flanger_stop},
--- a/src/misc.c
+++ b/src/misc.c
@@ -227,19 +227,20 @@
 }
 
 /* here for linear interp.  might be useful for other things */
-LONG gcd(a, b) 
+LONG st_gcd(a, b) 
 LONG a, b;
 {
 	if (b == 0)
 		return a;
 	else
-		return gcd(b, a % b);
+		return st_gcd(b, a % b);
 }
 
-LONG lcm(a, b)
+LONG st_lcm(a, b)
 LONG a, b;
 {
-	return (a * b) / gcd(a, b);
+    /* parenthesize this way to avoid LONG overflow in the product term */
+    return a * (b / st_gcd(a, b));
 }
 
 /* 
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -1,4 +1,3 @@
-
 /*
  * July 14, 1998
  * Copyright 1998  K. Bradley, Carnegie Mellon University
@@ -10,6 +9,16 @@
  */
 
 /*
+ * October 29, 1999
+ * Various changes, bugfixes, speedups, by Stan Brooks.
+ *
+ * This source code 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.
+ *
+ */
+
+/*
  * Sound Tools rate change effect file.
  */
 
@@ -21,27 +30,30 @@
 #endif
 #include "st.h"
 
-typedef struct _list {
-    int number;
-    float *data_buffer;
-    struct _list *next;
-} List;
+#define Float float/*double*/
+#define ISCALE 0x10000
+#define MF 30
 
+typedef struct {
+  int up,down;    /* up/down conversion factors for this stage      */
+  int filt_len;   /* # coefficients in filter_array                 */
+  Float *filt_array; /* filter coefficients                         */
+  int held;       /* # samples held in input but not yet processed  */
+  int hsize;      /* # samples of past-history kept in lower window */
+  int size;       /* # samples current data which window can accept */
+  Float *window;  /* this is past_hist[hsize], then input[size]     */
+} polystage;
+
 typedef struct polyphase {
 
-  unsigned long	lcmrate;	   /* least common multiple of rates */
-  unsigned long inskip, outskip;   /* LCM increments for I & O rates */
-  unsigned long total;
-  unsigned long intot, outtot;	   /* total samples in terms of LCM rate */
-  long	lastsamp;
+  unsigned long lcmrate;         /* least common multiple of rates */
+  unsigned long inskip, outskip; /* LCM increments for I & O rates */
+  double Factor;                 /* out_rate/in_rate               */
+  unsigned long total;           /* number of filter stages        */
+  unsigned long oskip;           /* output samples to skip at start*/
+  double inpipe;                 /* output samples 'in the pipe'   */
+  polystage *stage[MF];          /* array of pointers to polystage structs */
 
-  float **filt_array;
-  float **past_hist;
-  float *input_buffer;
-  int *filt_len;
-
-  List *l1, *l2;
-  
 } *poly_t;
 
 /*
@@ -53,8 +65,8 @@
    -w <nut / ham>        :  window type
    -width <short / long> :  window width
                             short = 128 samples
-			    long  = 1024 samples
-	  <num>	            num:  explicit number
+                            long  = 1024 samples
+   <num>                    num:  explicit number
  
    -cutoff <float>       :  frequency cutoff for base bandwidth.
                             Default = 0.95 = 95%
@@ -62,12 +74,9 @@
 
 static int win_type  = 0;
 static int win_width = 1024;
-static float cutoff = 0.95;
+static Float cutoff = 0.95;
    
-void poly_getopts(effp, n, argv) 
-eff_t effp;
-int n;
-char **argv;
+void poly_getopts(eff_t effp, int n, char **argv) 
 {
   /* 0: nuttall
      1: hamming */
@@ -85,9 +94,9 @@
     /* Window type check */
     if(!strcmp(argv[0], "-w")) {
       if(!strcmp(argv[1], "ham"))
-	win_type = 1;
+        win_type = 1;
       if(!strcmp(argv[1], "nut"))
-	win_type = 0;
+        win_type = 0;
 
       argv += 2;
       n -= 2;
@@ -97,11 +106,11 @@
     /* Window width check */
     if(!strcmp(argv[0], "-width")) {
       if(!strcmp(argv[1], "short"))
-	win_width = 128;
+        win_width = 128;
       else if(!strcmp(argv[1], "long"))
-	win_width = 1024;
+        win_width = 1024;
       else
-	win_width = atoi(argv[1]);
+        win_width = atoi(argv[1]);
 
       argv += 2;
       n -= 2;
@@ -123,8 +132,7 @@
 /*
  * Prepare processing.
  */
-
-static int primes[] = {
+static const unsigned short primes[] = {
   2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
   41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
   97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
@@ -138,7 +146,8 @@
   661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743,
   751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
   829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
-  919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997
+  919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
+  0
 };
 
 #ifndef max
@@ -145,56 +154,127 @@
 #define max(x,y) ((x > y) ? x : y)
 #endif
 
-List *prime(number)
-int number;
+#ifndef min
+#define min(x,y) ((x < y) ? x : y)
+#endif
+
+static int prime(int n, int *q0)
 {
-    int j;
-    List *element = NULL;
+  const unsigned short *p;
+  int pr, *q;
 
-    if(number == 1)
-      return NULL;
-
-    for(j=167;j>= 0;j--) {
-	if(number % primes[j] == 0) {
-	    element = (List *) malloc(sizeof(List));
-	    element->number = primes[j];
-	    element->data_buffer = NULL;
-	    element->next = prime(number / primes[j]);
-	    break;
-	}
+  p = primes;
+  q = q0;
+  report("factors(%d) =",n);
+  while (n > 1) {
+    while ((pr = *p) && (n % pr)) p++;
+    if (!pr) {
+      fail("Number %d too large of a prime.\n",n);
+      pr = n;
     }
+    *q++ = pr;
+    n /= pr;
+  }
+  *q = 0;
+  for (pr=0; pr<q-q0; pr++) fprintf(stderr," %d",q0[pr]);
+  fprintf(stderr,"\n");
+  return (q-q0);
+}
 
-    if(element == NULL) {
-	fail("Number %d too large of a prime.\n",number);
-    }
+static int permute(int *m, int *l, int ct, int ct1, int amalg)
+{
+  int k, n;
+  int *p;
+  int *q;
 
-    return element;
+  p=l; q=m;
+  while (ct1>ct) { *q++=1; ct++;} 
+  while ((*q++=*p++)) ;
+  if (ct<=1) return ct;
+  
+  for (k=ct; k>1; ) {
+    int tmp, j;
+    j = random() % k;
+    k--;
+    if (j != k) {
+      tmp = m[k]; m[k]=m[j]; m[j]=tmp;
+    }
+  }
+  /* now m is a 'random' permutation of l */
+  p = q = m;
+  n = *q++;
+  while ((k=*q++)) {
+    if ((n * k <= amalg) && (random() & 1)) {
+      n *= k;
+    } else {
+      *p++ = n;
+      n = k;
+    }
+  }
+  if (n) *p++=n;
+  *p = 0;
+  /*for (k=0; k<p-m; k++) fprintf(stderr," %d",m[k]);*/
+  /*fprintf(stderr,"\n");*/
+  return (p-m);
 }
 
-List *prime_inv(number)
-int number;
+static int optimize_factors(int numer, int denom, int *l1, int *l2)
 {
-    int j;
-    List *element = NULL;
+  int f_min,c_min,u_min,ct1,ct2;
+  int amalg;
+  int k;
+  static int m1[MF],m2[MF];
+  static int b1[MF],b2[MF];
 
-    if(number == 1)
-      return NULL;
+  f_min = numer; if (f_min>denom) f_min = denom;
+  c_min = 1<<30;
+  u_min = 0;
 
-    for(j=0;j<168;j++) {
-	if(number % primes[j] == 0) {
-	    element = (List *) malloc(sizeof(List));
-	    element->number = primes[j];
-	    element->data_buffer = NULL;
-	    element->next = prime_inv(number / primes[j]);
-	    break;
-	}
-    }
+  /* Find the prime factors of numer and denom */
+  ct1 = prime(numer,l1);
+  ct2 = prime(denom,l2);
 
-    if(element == NULL) {
-	fail("Number %d too large of a prime.\n",number);
+  for (amalg = max(9,l2[0]); amalg<= 9+l2[ct2-1]; amalg++) {
+    for (k = 0; k<100000; k++) {
+      int u,u1,u2,j,f,cost;
+      cost = 0;
+      f = denom;
+      u = min(ct1,ct2) + 1;
+      /*fprintf(stderr,"pfacts(%d): ", numer);*/
+      u1 = permute(m1,l1,ct1,u,amalg);
+      /*fprintf(stderr,"pfacts(%d): ", denom);*/
+      u2 = permute(m2,l2,ct2,u,amalg);
+      u = max(u1,u2);
+      for (j=0; j<u; j++) {
+        if (j>=u1) m1[j]=1;
+        if (j>=u2) m2[j]=1;
+        f = (f * m1[j])/m2[j];
+        if (f < f_min) goto fail;
+        cost += f + m1[j]*m2[j];
+      }
+      if (c_min>cost) {
+        c_min = cost;
+        u_min = u;
+#       if 0
+        fprintf(stderr,"c_min %d, [%d-%d]:",c_min,numer,denom);
+        for (j=0; j<u; j++)
+          fprintf(stderr," (%d,%d)",m1[j],m2[j]);
+        fprintf(stderr,"\n");
+#       endif
+       memcpy(b1,m1,u*sizeof(int));
+       memcpy(b2,m2,u*sizeof(int));
+      }
+     fail:
     }
-
-    return element;
+    if (u_min) break;
+  }
+  if (u_min) {
+    memcpy(l1,b1,u_min*sizeof(int));
+    memcpy(l2,b2,u_min*sizeof(int));
+  }
+  l1[u_min] = 0;
+  l2[u_min] = 0;
+  return u_min;
 }
 
 #ifndef PI
@@ -205,20 +285,18 @@
    Buffer must already be allocated to appropriate size.
    */
 
-void nuttall(buffer, length)
-float *buffer;
-int length;
+static void nuttall(Float *buffer, int length)
 {
   int j;
   double N;
-  double N1;
+  int N1;
 
-  if(buffer == NULL || length < 0)
+  if(buffer == NULL || length <= 0)
     fail("Illegal buffer %p or length %d to nuttall.\n", buffer, length);
 
   /* Initial variable setups. */
-  N = (double) length - 1.0;
-  N1 = N / 2.0;
+  N = length;
+  N1 = length/2;
 
   for(j = 0; j < length; j++) {
     buffer[j] = 0.36335819 + 
@@ -231,23 +309,22 @@
    Buffer must already be allocated to appropriate size.
 */
 
-void hamming(buffer, length)
-float *buffer;
-int length;
+static void hamming(Float *buffer, int length)
 {
     int j;
+    int N1;
 
-    if(buffer == NULL || length < 0)
+    if(buffer == NULL || length <= 0)
       fail("Illegal buffer %p or length %d to hamming.\n",buffer,length);
 
+    N1 = length/2;
     for(j=0;j<length;j++) 
-      buffer[j] = 0.5 - 0.46 * cos(2*PI*j/(length-1));
+      buffer[j] = 0.5 - 0.46 * cos(PI*j/N1);
 }
 
 /* Calculate the sinc function properly */
 
-float sinc(value)
-float value;
+static Float sinc(Float value)
 {   
     return(fabs(value) < 1E-50 ? 1.0 : sin(value) / value);
 }
@@ -258,55 +335,50 @@
 
    buffer must already be allocated.
 */
-void fir_design(buffer, length, cutoff)
-float *buffer;
-int length;
-float cutoff;
+void fir_design(Float *buffer, int length, Float cutoff)
 {
     int j;
-    float sum;
-    float *ham_win;
+    double sum;
 
     if(buffer == NULL || length < 0 || cutoff < 0 || cutoff > PI)
       fail("Illegal buffer %p, length %d, or cutoff %f.\n",buffer,length,cutoff);
 
-    /* Design Hamming window:  43 dB cutoff */
-    ham_win = (float *)malloc(sizeof(float) * length);
-
     /* Use the user-option of window type */
     if(win_type == 0) 
-      nuttall(ham_win, length);
+      nuttall(buffer, length); /* Design Nuttall window:  ** dB cutoff */
     else
-      hamming(ham_win,length);
+      hamming(buffer,length);  /* Design Hamming window:  43 dB cutoff */
 
+    /* printf("# fir_design length=%d, cutoff=%8.4f\n",length,cutoff); */
     /* Design filter:  windowed sinc function */
     sum = 0.0;
     for(j=0;j<length;j++) {
-	buffer[j] = sinc(PI*cutoff*(j-length/2)) * ham_win[j] / (2*cutoff);
-	sum += buffer[j];
+      buffer[j] *= sinc(PI*cutoff*(j-length/2)); /* center at length/2 */
+      /* printf("%.1f %.6f\n",(float)j,buffer[j]); */
+      sum += buffer[j];
     }
-
+    sum = (double)1.0/sum;
     /* Normalize buffer to have gain of 1.0: prevent roundoff error */
-    for(j=0;j<length;j++)
-      buffer[j] /= sum;
-
-    free((void *) ham_win);
+    for(j=0;j<length;j++) {
+      buffer[j] *= sum;
+    }
+    /* printf("# end\n\n"); */
 }
-    
+ 
+#define RIBLEN 2048
 
-void poly_start(effp)
-eff_t effp;
+void poly_start(eff_t effp)
 {
     poly_t rate = (poly_t) effp->priv;
-    List *t, *t2;
-    int num_l1, num_l2;
-    int j,k;
-    float f_cutoff;
+    static int l1[MF], l2[MF];
+    double skip = 0;
+		int total, size, uprate;
+    int k;
 
-    extern long lcm();
-	
-    rate->lcmrate = lcm((long)effp->ininfo.rate, (long)effp->outinfo.rate);
+    extern long st_lcm();
 
+    rate->lcmrate = st_lcm((long)effp->ininfo.rate, (long)effp->outinfo.rate);
+
     /* Cursory check for LCM overflow.  
      * If both rate are below 65k, there should be no problem.
      * 16 bits x 16 bits = 32 bits, which we can handle.
@@ -314,155 +386,76 @@
 
     rate->inskip = rate->lcmrate / effp->ininfo.rate;
     rate->outskip = rate->lcmrate / effp->outinfo.rate; 
+    rate->Factor = (double)rate->inskip / (double)rate->outskip; 
+    rate->inpipe = 0; 
+    {
+      int f = RIBLEN/max(rate->inskip,rate->outskip);
+      if (f == 0) f = 1;
+      size = f * rate->outskip; /* reasonable input block size */
+    }
 
     /* Find the prime factors of inskip and outskip */
-    rate->l1 = prime(rate->inskip);
+    total = optimize_factors(rate->inskip, rate->outskip, l1, l2);
+    rate->total = total;
+    /* l1 and l2 are now lists of the up/down factors for conversion */
 
-    /* If we're going up, order things backwards. */
-    if(effp->ininfo.rate < effp->outinfo.rate)
-      rate->l2 = prime_inv(rate->outskip);
-    else
-      rate->l2 = prime(rate->outskip);
-    
-    /* Find how many factors there were */
-    if(rate->l1 == NULL)
-      num_l1 = 0;
-    else
-      for(num_l1=0, t = rate->l1; t != NULL; num_l1++, t=t->next);
+    report("Poly:  input rate %d, output rate %d.  %d stages.",
+            effp->ininfo.rate, effp->outinfo.rate,total);
+    report("Poly:  window: %s  size: %d  cutoff: %f.",
+            (win_type == 0) ? ("nut") : ("ham"), win_width, cutoff);
 
-    if(rate->l2 == NULL) 
-      num_l2 = 0;
-    else
-      for(num_l2=0, t = rate->l2; t != NULL; num_l2++, t=t->next);
+    /* Create an array of filters and past history */
+    uprate = effp->ininfo.rate;
+    for (k = 0; k < total; k++) {
+      int j, prod, f_cutoff, f_len;
+      polystage *s;
 
-    k = 0;
-    t = rate->l1;
+      rate->stage[k] = s = (polystage*) malloc(sizeof(polystage));
+      s->up = l1[k];
+      s->down = l2[k];
+      f_cutoff = max(s->up, s->down);
+      f_len = max(20 * f_cutoff, win_width);
+      prod = s->up * s->down;
+      if (prod > 2*f_len) prod = s->up;
+      f_len = ((f_len+prod-1)/prod) * prod; /* reduces rounding-errors in polyphase() */
+      s->size = size;
+      s->hsize = f_len/s->up; /* this much of window is past-history */
+      s->held = 0;
+      report("Poly:  stage %d:  Up by %d, down by %d,  i_samps %d, hsize %d",
+              k+1,s->up,s->down,size, s->hsize);
+      s->filt_len = f_len;
+      s->filt_array = (Float *) malloc(sizeof(Float) * f_len);
+      s->window = (Float *) malloc(sizeof(Float) * (s->hsize+size));
+      /* zero past_history section of window */
+      for(j = 0; j < s->hsize; j++)
+        s->window[j] = 0.0;
 
-    /* Compact the lists to be less than 10 */
-    while(k < num_l1 - 1) {
-	if(t->number * t->next->number < 10) {
-	    t->number = t->number * t->next->number;
-	    t2 = t->next;
-	    t->next = t->next->next;
-	    t2->next = NULL;
-	    free((void *) t2);
-	    num_l1--;
-	} else {
-	    k++;
-	    t = t->next;
-	}
-    }
+      uprate *= s->up;
+      report("Poly:         :  filt_len %d, cutoff freq %.1f",
+              f_len, uprate*cutoff/f_cutoff);
+      uprate /= s->down;
+      fir_design(s->filt_array, f_len, cutoff/f_cutoff);
+      /* s->filt_array[f_len-1]=0; */
 
-    k = 0;
-    t = rate->l2;
+			skip *= s->up;
+			skip += f_len;
+			skip /= s->down;
 
-    while(k < num_l2 - 1) {
-	if(t->number * t->next->number < 10) {
-	    t->number = t->number * t->next->number;
-	    t2 = t->next;
-	    t->next = t->next->next;
-	    t2->next = NULL;
-	    free((void *) t2);
-	    num_l2--;
-	} else {
-	    k++;
-	    t = t->next;
-	}
+			size = (size * s->up) / s->down;  /* this is integer */
     }
-
-    /* l1 and l2 are now lists of the prime factors compacted,
-       meaning that they're the lists of up/down sampling we need
-       */
-
-    /* Stretch them to be the same length by padding with 1 (no-op) */
-    if(num_l1 < num_l2) {
-	t = rate->l1;
-
-	if(t == NULL) {
-	    rate->l1 = (List *)malloc(sizeof(List));
-	    rate->l1->next = NULL;
-	    rate->l1->number = 1;
-	    rate->l1->data_buffer = NULL;
-	    t = rate->l1;
-	    num_l1++;
-	}
-
-	while(t->next != NULL)
-	  t = t->next;
-
-	for(k=0;k<num_l2-num_l1;k++) {
-	    t->next = (List *) malloc(sizeof(List));
-	    t->next->number = 1;
-	    t->next->data_buffer = NULL;
-	    t = t->next;
-	}
-
-	t->next = NULL;
-	num_l1 = num_l2;
-    } else {
-	t = rate->l2;
-
-	if(t == NULL) {
-	    rate->l2 = (List *)malloc(sizeof(List));
-	    rate->l2->next = NULL;
-	    rate->l2->number = 1;
-	    rate->l2->data_buffer = NULL;
-	    t = rate->l2;
-	    num_l2++;
-	}
-	  
-	/*
-	  while(t->next != NULL)
-	  t = t->next;
-	  */
-
-	for(k=0;k<num_l1-num_l2;k++) {
-	  t = rate->l2;
-	  rate->l2 = (List *) malloc(sizeof(List));
-	  rate->l2->number = 1;
-	  rate->l2->data_buffer = NULL;
-	  rate->l2->next = t;
-	}
-
-	/* t->next = NULL; */
-	num_l2 = num_l1;
+    rate->oskip = skip/2;
+		{ /* bogus last stage is for output buffering */
+      polystage *s;
+      rate->stage[k] = s = (polystage*) malloc(sizeof(polystage));
+      s->up = s->down = 0;
+      s->size = size;
+      s->hsize = 0;
+      s->held = 0;
+      s->filt_len = 0;
+      s->filt_array = NULL;
+      s->window = (Float *) malloc(sizeof(Float) * size);
     }
-
-    /* l1 and l2 are now the same size. */
-    rate->total = num_l1;
-
-    report("Poly:  input rate %d, output rate %d.  %d stages.",effp->ininfo.rate, effp->outinfo.rate,num_l1);
-    report("Poly:  window: %s  size: %d  cutoff: %f.", (win_type == 0) ? ("nut") : ("ham"), win_width, cutoff);
-
-    for(k=0, t=rate->l1, t2=rate->l2;k<num_l1;k++,t=t->next,t2=t2->next)
-      report("Poly:  stage %d:  Up by %d, down by %d.",k+1,t->number,t2->number);
-
-    /* We'll have an array of filters and past history */
-    rate->filt_array = (float **) malloc(sizeof(float *) * num_l1);
-    rate->past_hist = (float **) malloc(sizeof(float *) * num_l1);
-    rate->filt_len = (int *) malloc(sizeof(int) * num_l1);
-
-    for(k = 0, t = rate->l1, t2 = rate->l2; k < num_l1; k++) {
-
-      rate->filt_len[k] = max(2 * 10 * max(t->number,t2->number), win_width);
-      rate->filt_array[k] = (float *) malloc(sizeof(float) * rate->filt_len[k]);
-      rate->past_hist[k] = (float *) malloc(sizeof(float) * rate->filt_len[k]);
-      
-      t->data_buffer = (float *) malloc(sizeof(float) * 1024 * rate->inskip);
-	
-      for(j = 0; j < rate->filt_len[k]; j++)
-	rate->past_hist[k][j] = 0.0;
-
-      f_cutoff = (t->number > t2->number) ? 
-	(float) t->number : (float) t2->number;
-
-      fir_design(rate->filt_array[k], rate->filt_len[k]-1, cutoff / f_cutoff);
-
-      t = t->next;
-      t2 = t2->next;
-    }
-
-    rate->input_buffer = (float *) malloc(sizeof(float) * 2048);
+    report("Poly:  output samples %d, oskip %d",size, rate->oskip);
 }
 
 /*
@@ -470,141 +463,155 @@
  * Return number of samples processed.
  */
 
-static float *h;
-static int M, L, N;
-
-void polyphase_init(coef, num_coef, up_rate, down_rate)
-float *coef;
-int num_coef;
-int up_rate;
-int down_rate;
+/* REMARK: putting this in a separate subroutine improves gcc's optimization */
+static double st_prod(const Float *q, int qstep, const Float *p, int n)
 {
-    h = coef;
-    M = down_rate;
-    L = up_rate;
-    N = num_coef;
+  double sum = 0;
+  const Float *p0;
+  p0 = p-n;
+  while (p>p0) {
+    sum += *p * *q;
+    q += qstep;
+    p -= 1;
+  }
+  return sum;
 }
     
-void polyphase(input, output, past, num_samples_input)
-float *input;
-float *output;
-float *past;
-int num_samples_input;
+void polyphase(Float *output, polystage *s)
 {
-    int num_output;
-    int m,n;
-    float sum;
-    float inp;
-    int base;
-    int h_base;
+  int mm;
+  int up = s->up;
+  int down = s->down;
+  int f_len = s->filt_len;
+  const Float *in;
+  Float *o; /* output pointer */
+  Float *o_top;
 
-    num_output = num_samples_input * L / M;
+  in = s->window + s->hsize;
+  /*for (mm=0; mm<s->filt_len; mm++) fprintf(stderr,"cf_%d %f\n",mm,s->filt_array[mm]);*/
+  /* assumes s->size divisible by down (now true) */
+  o_top = output + (s->size * up) / down;
+  /*report(" isize %d, osize %d, up %d, down %d, N %d", s->size, o_top-output, up, down, f_len);*/
+  for (mm=0, o=output; o < o_top; mm+=down, o++) {
+    double sum;
+    const Float *p, *q;
+    q = s->filt_array + (mm%up);   /* decimated coef pointer */
+    p  = in + (mm/up);
+    sum = st_prod(q, up, p, f_len/up);
+    *o = sum * up;
+  }
+}
 
-    for(m=0;m<num_output;m++) {
-	sum = 0.0;
-	base = (int) (m*M/L);
-	h_base = (m*M) % L;
+static inline void update_hist(Float *hist, int hist_size, int in_size)
+{
+  Float *p, *p1, *q;
+  p = hist;
+  p1 = hist+hist_size;
+  q = hist+in_size;
+  while (p<p1)
+    *p++ = *q++;
 
-	for(n=0;n<N / L;n++) {
-	    if(base - n < 0)
-	      inp = past[base - n + N];
-	    else
-	      inp = input[base - n];
-
-	    sum += h[n*L + h_base] * inp;
-	}
-
-	output[m] = sum * L * 0.95;
-    }
 }
 
-void poly_flow(effp, ibuf, obuf, isamp, osamp)
-eff_t effp;
-long *ibuf, *obuf;
-int *isamp, *osamp;
+void poly_flow(eff_t effp, long *ibuf, long *obuf, long *isamp, long *osamp)
 {
   poly_t rate = (poly_t) effp->priv;
-  float *temp_buf, *temp_buf2;
-  int j,k;
-  List *t1, *t2;
-  int in_size, out_size;
+  polystage *s0,*s1;
 
   /* Sanity check:  how much can we tolerate? */
-  in_size = *isamp;
-  out_size = in_size * rate->inskip / rate->outskip;
-  if(out_size > *osamp) {
-    in_size = *osamp * rate->outskip / rate->inskip;
-    *isamp = in_size;
+  /* fprintf(stderr, "*isamp=%d *osamp=%d\n",*isamp,*osamp); fflush(stderr); */
+  s0 = rate->stage[0];            /* the first stage */
+  s1 = rate->stage[rate->total];  /* the 'last' stage is output buffer */
+  {
+    int in_size, gap, k;
+    
+    in_size = *isamp;
+    gap = s0->size - s0->held; /* space available in this 'input' buffer */
+    if ((in_size > gap) || (ibuf==NULL)) {
+      *isamp = in_size = gap;
+    }
+    if (in_size > 0) {
+      Float *q;
+			q = s0->window + s0->hsize;
+      if (s0!=s1) q += s0->held;  /* the last (output) buffer doesn't shift history */
+      if (ibuf != NULL) {
+				rate->inpipe += rate->Factor * in_size;
+        for (k=0; k<in_size; k++)
+          *q++ = (Float)ibuf[k] / ISCALE;
+      } else { /* ibuf==NULL is draining */
+        for(k=0;k<in_size;k++)
+          *q++ = 0.0;
+      }
+      s0->held += in_size;
+    }
   }
+
+  if (s0->held == s0->size && s1->held == 0) {
+    int k;
+    /* input buffer full, output buffer empty, so do process */
+
+    for(k=0; k<rate->total; k++) {
+      polystage *s;
+      Float *out;
   
-  /* Check to see if we're really draining */
-  if(ibuf != NULL) {
-    for(k=0;k<*isamp;k++)
-      rate->input_buffer[k] = (float) (ibuf[k] >> 16);
-  } else {
-    for(k=0;k<*isamp;k++)
-      rate->input_buffer[k] = 0.0;
-  }      
+      s = rate->stage[k];
   
-  temp_buf = rate->input_buffer;
+      out = rate->stage[k+1]->window + rate->stage[k+1]->hsize;
   
-  t1 = rate->l1;
-  t2 = rate->l2;
-  
-  for(k=0;k<rate->total;k++,t1=t1->next,t2=t2->next) {
-    
-    polyphase_init(rate->filt_array[k], rate->filt_len[k], 
-		   t1->number,t2->number);
-    
-    out_size = (in_size) * t1->number / t2->number;
-    
-    temp_buf2 = t1->data_buffer;
-    
-    polyphase(temp_buf, temp_buf2, rate->past_hist[k], in_size);
-    
-    for(j = 0; j < rate->filt_len[k]; j++) 
-      rate->past_hist[k][j] = temp_buf[j+in_size - rate->filt_len[k]];
-    
-    in_size = out_size;
-    
-    temp_buf = temp_buf2;
+      /* fprintf(stderr, "k=%d  insize=%d\n",k,in_size); fflush(stderr); */
+      polyphase(out, s);
+   
+      /* copy input history into lower portion of rate->window[k] */
+      update_hist(s->window, s->hsize, s->size);
+      s->held = 0;
+    }
+
+    s1->held = s1->size;
+    s1->hsize = 0;
+
   }
-  
-  if(out_size > *osamp)
-    out_size = *osamp;
-  
-  *osamp = out_size;
 
-  if(ibuf != NULL) {
-    for(k=0;k < out_size;k++)
-      obuf[k] = ((int) temp_buf[k]) << 16;
-  } else {
+  {
+    long *q;
+    long out_size;
+    long oskip;
+    Float *out_buf;
+    int k;
 
-    /* Wait for all-zero samples to come through.
-       Should happen eventually with all-zero
-       input */
-    int found = 0;
+    oskip = rate->oskip;
+		out_size = s1->held;
+		out_buf = s1->window + s1->hsize;
 
-    for(k=0; k < out_size; k++) {
-      obuf[k] = ((int) temp_buf[k] << 16);
-      if(obuf[k] != 0)
-	found = 1;
+    if(ibuf == NULL && out_size > ceil(rate->inpipe)) {
+      out_size = ceil(rate->inpipe);
     }
-    if(!found)
-      *osamp = 0;
+
+		if (out_size > oskip + *osamp) out_size = oskip + *osamp;
+
+    for(q=obuf, k=oskip; k < out_size; k++)
+      *q++ = out_buf[k] * ISCALE; /* should clip-limit */
+
+		*osamp = q-obuf;
+		rate->inpipe -= *osamp;
+		oskip -= out_size - *osamp;
+		rate->oskip = oskip;
+
+		s1->hsize += out_size;
+    s1->held -= out_size;
+    if (s1->held == 0) {
+      s1->hsize = 0;
+    }
+
   }
+
 }
 
 /*
  * Process tail of input samples.
  */
-void poly_drain(effp, obuf, osamp)
-eff_t effp;
-long *obuf;
-long *osamp;
+void poly_drain(eff_t effp, long *obuf, long *osamp)
 {
-  long in_size = 1024;
-
+  long in_size;
   /* Call "flow" with NULL input. */
   poly_flow(effp, NULL, obuf, &in_size, osamp);
 }
@@ -613,39 +620,16 @@
  * Do anything required when you stop reading samples.  
  * Don't close input file! 
  */
-void poly_stop(effp)
-eff_t effp;
+void poly_stop(eff_t effp)
 {
-    List *t, *t2;
     poly_t rate = (poly_t) effp->priv;
+    polystage *s;
     int k;
 
-    /* Free lists */
-    for(t = rate->l1; t != NULL; ) {
-	t2 = t->next;
-	t->next = NULL;
-	if(t->data_buffer != NULL)
-	  free((void *) t->data_buffer);
-	free((void *) t);
-	t = t2;
+    for(k = 0; k <= rate->total; k++) {
+      s = rate->stage[k];
+      free((void *) s->window);
+      if (s->filt_array) free((void *) s->filt_array);
+      free((void *) s);
     }
-
-    for(t = rate->l2; t != NULL; ) {
-	t2 = t->next;
-	t->next = NULL;
-	if(t->data_buffer != NULL)
-	  free((void *) t->data_buffer);
-	free((void *) t);
-	t = t2;
-    }
-
-    for(k = 0; k < rate->total;k++) {
-	free((void *) rate->past_hist[k]);
-	free((void *) rate->filt_array[k]);
-    }
-
-    free((void *) rate->past_hist);
-    free((void *) rate->filt_array);
-    free((void *) rate->filt_len);
 }
-
--- a/src/raw.c
+++ b/src/raw.c
@@ -26,8 +26,13 @@
 #include <malloc.h>
 #endif
 
+#include <string.h>
 #include <stdlib.h>
 
+#ifndef HAVE_MEMMOVE
+#define memmove(dest, src, len) bcopy((src), (dest), (len))
+#endif
+
 void rawstartread(ft) 
 ft_t ft;
 {
@@ -59,8 +64,7 @@
 	{
 		if (ft->file.eof)
 			return(0);
-		ft->file.count = fread(ft->file.buf, 1, ft->file.size,
-				ft->fp);
+		ft->file.count = fread(ft->file.buf, 1, ft->file.size, ft->fp);
 		ft->file.pos = 0;
 		if (ft->file.count == 0)
 		{
@@ -72,63 +76,49 @@
 	return (rval);
 }
 
-unsigned short blockrshort(ft)
-ft_t ft;
+static void swapn(p, n)
+char *p;
+int n;
 {
-	unsigned short rval;
-	if (ft->file.pos > ft->file.count-2)
-	{
-		if (ft->file.eof)
-			return(0);
-
-		if (ft->file.pos == ft->file.count-1)
-		{
-			*ft->file.buf = *(ft->file.buf + ft->file.pos);
-			ft->file.count = fread(ft->file.buf + 1,
-					1, ft->file.size-1,
-					ft->fp);
+	char *q;
+	if (n>1) {
+		q = p+n-1;
+		while (q>p) {
+			char t = *q;
+			*q-- = *p;
+			*p++ = t;
 		}
-		else
-		{
-			ft->file.count = fread(ft->file.buf, 1, ft->file.size,
-					ft->fp);
-		}
-		ft->file.pos = 0;
-		if (ft->file.count < 2)
-		{
-			ft->file.eof = 1;
-			return(0);
-		}
 	}
-	rval = *((unsigned short *)(ft->file.buf + ft->file.pos));
-	ft->file.pos += 2;
-	if (ft->swap)
-		rval = swapw(rval);
-	return(rval);
 }
 
-float blockrfloat(ft)
+static void blockr(p0, n, ft)
 ft_t ft;
+int n;
+void *p0;
 {
-	float rval;
-
-	if (ft->file.count < sizeof(float))
+	int rest;
+	char *p;
+	p = p0;
+	
+	while ((rest = ft->file.count - ft->file.pos) < n)
 	{
-		ft->file.count = fread(ft->file.buf, 1, ft->file.size,
-				ft->fp);
-		if (ft->file.count == 0)
-		{
-			ft->file.eof = 1;
-			return(0);
+		if (ft->file.eof) {
+			memset(p,0,n);
+			return;
 		}
+
+		memmove(ft->file.buf, ft->file.buf+ft->file.pos, rest);
+
+		ft->file.pos = 0;
+		ft->file.count = rest;
+		ft->file.count += fread(ft->file.buf+rest, 1, ft->file.size-rest, ft->fp);
+		ft->file.eof = (ft->file.count < n);
 	}
-	rval = *((float *)(ft->file.buf + (ft->file.size - ft->file.count)));
-	ft->file.count -= sizeof(float);
+	memcpy(p, ft->file.buf + ft->file.pos, n);
+	ft->file.pos += n;
 	if (ft->swap)
-		rval = swapf(rval);
-	return(rval);
+		swapn(p,n);
 }
-	
 
 LONG rawread(ft, buf, nsamp) 
 ft_t ft;
@@ -193,7 +183,9 @@
 		    {
 			case SIGN2:
 				while(done < nsamp) {
-					datum = blockrshort(ft);
+					short s;
+					blockr(&s, sizeof(short), ft);
+					datum = s;
 					if (ft->file.eof)
 						return done;
 					/* scale signed up to long's range */
@@ -203,7 +195,9 @@
 				return done;
 			case UNSIGNED:
 				while(done < nsamp) {
-					datum = blockrshort(ft);
+					unsigned short s;
+					blockr(&s, sizeof(short), ft);
+					datum = s;
 					if (ft->file.eof)
 						return done;
 					/* Convert to signed */
@@ -221,12 +215,28 @@
 				return done;
 		    }
 		    break;
+		case DWORD:
+		    switch(ft->info.style)
+		    {
+			case SIGN2:
+				while(done < nsamp) {
+					blockr(buf, sizeof(LONG), ft);
+					if (ft->file.eof)
+						return done;
+					/* scale signed up to long's range */
+					buf++;
+					done++;
+				}
+				return done;
+		    }
+		    break;
 		case FLOAT:
 			while(done < nsamp) {
-				datum = blockrfloat(ft);
+				float f;
+				blockr(&f, sizeof(float), ft);
 				if (ft->file.eof)
 					return done;
-				*buf++ = LEFT(datum, 16);
+				*buf++ = f * 0x10000; /* hmm... */
 				done++;
 			}
 			return done;
@@ -244,7 +254,7 @@
 	free(ft->file.buf);
 }
 
-void blockflush(ft)
+static void blockflush(ft)
 ft_t ft;
 {
 	if (fwrite(ft->file.buf, 1, ft->file.pos, ft->fp) != ft->file.pos)
@@ -263,33 +273,22 @@
 	ft->file.pos++;
 }
 
-void blockwshort(ft,ui)
+static void blockw(p0, n, ft)
+void *p0;
+int n;
 ft_t ft;
-unsigned short ui;
 {
-	if (ft->file.pos > ft->file.size-2) blockflush(ft);
+	if (ft->file.pos > ft->file.size-n) blockflush(ft);
+	memcpy(ft->file.buf + ft->file.pos, p0, n);
 	if (ft->swap)
-		ui = swapw(ui);
-	*(unsigned short *)(ft->file.buf + ft->file.pos) = ui;
-	ft->file.pos += 2;
+		swapn(ft->file.pos, n);
+	ft->file.pos += n;
 }
 
-void blockwfloat(ft,f)
-ft_t ft;
-float f;
-{
-	if (ft->file.pos > ft->file.size - sizeof(float)) blockflush(ft);
-	if (ft->swap)
-		f = swapf(f);
-	*(float *)(ft->file.buf + ft->file.pos) = f;
-	ft->file.pos += sizeof(float);
-}
-
 /* Convert the sox internal signed long format */
 /* to the raw file data, and write it. */
 
-void
-rawwrite(ft, buf, nsamp) 
+void rawwrite(ft, buf, nsamp) 
 ft_t ft;
 LONG *buf, nsamp;
 {
@@ -347,19 +346,22 @@
 		    {
 			case SIGN2:
 				while(done < nsamp) {
+					short s;
 					/* scale signed up to long's range */
-					datum = (int) RIGHT(*buf++, 16);
-					blockwshort(ft, datum);
+					datum = *buf++ + 0x8000; /* round for 16 bit */
+					s = RIGHT(datum, 16);
+					blockw(&s, sizeof(short),ft);
 					done++;
 				}
 				return;
 			case UNSIGNED:
 				while(done < nsamp) {
+					unsigned short s;
 					/* scale signed up to long's range */
-					datum = (int) RIGHT(*buf++, 16);
+					datum = *buf++ + 0x8000; /* round for 16 bit */
+					s = RIGHT(datum, 16) ^ 0x8000;
 					/* Convert to unsigned */
-					datum ^= 0x8000;
-					blockwshort(ft, datum);
+					blockw(&s, sizeof(short),ft);
 					done++;
 				}
 				return;
@@ -371,11 +373,25 @@
 				return;
 		    }
 		    break;
+		case DWORD:
+		    switch(ft->info.style)
+		    {
+			case SIGN2:
+				while(done < nsamp) {
+					/* scale signed up to long's range */
+					blockw(buf, sizeof(LONG), ft);
+					buf++;
+					done++;
+				}
+				return;
+		    }
+		    break;
 		case FLOAT:
 			while(done < nsamp) {
+				float f;
 				/* scale signed up to long's range */
-				datum = (int) RIGHT(*buf++, 16);
-			 	blockwfloat(ft, (double) datum);
+				f = (float)*buf++ / 0x10000;
+			 	blockw(&f, sizeof(float), ft);
 				done++;
 			}
 			return;
@@ -400,115 +416,47 @@
 
 void rawdefaults();
 
-/* Signed byte */
-void sbstartread(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = SIGN2;
-	rawstartread(ft);
-	rawdefaults(ft);
+#define STARTREAD(NAME,SIZE,STYLE) \
+void NAME(ft) \
+ft_t ft; \
+{ \
+	ft->info.size = SIZE; \
+	ft->info.style = STYLE; \
+	rawstartread(ft); \
+	rawdefaults(ft); \
 }
 
-void sbstartwrite(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = SIGN2;
-	rawstartwrite(ft);
-	rawdefaults(ft);
+#define STARTWRITE(NAME,SIZE,STYLE)\
+void NAME(ft) \
+ft_t ft; \
+{ \
+	ft->info.size = SIZE; \
+	ft->info.style = STYLE; \
+	rawstartwrite(ft); \
+	rawdefaults(ft); \
 }
 
-void ubstartread(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = UNSIGNED;
-	rawstartread(ft);
-	rawdefaults(ft);
-}
+STARTREAD(sbstartread,BYTE,SIGN2) 
+STARTREAD(sbstartwrite,BYTE,SIGN2) 
 
-void ubstartwrite(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = UNSIGNED;
-	rawstartwrite(ft);
-	rawdefaults(ft);
-}
+STARTREAD(ubstartread,BYTE,UNSIGNED) 
+STARTREAD(ubstartwrite,BYTE,UNSIGNED) 
 
-void uwstartread(ft) 
-ft_t ft;
-{
-	ft->info.size = WORD;
-	ft->info.style = UNSIGNED;
-	rawstartread(ft);
-	rawdefaults(ft);
-}
+STARTREAD(uwstartread,WORD,UNSIGNED) 
+STARTREAD(uwstartwrite,WORD,UNSIGNED) 
 
-void uwstartwrite(ft) 
-ft_t ft;
-{
-	ft->info.size = WORD;
-	ft->info.style = UNSIGNED;
-	rawstartwrite(ft);
-	rawdefaults(ft);
-}
+STARTREAD(swstartread,WORD,SIGN2) 
+STARTREAD(swstartwrite,WORD,SIGN2) 
 
-void swstartread(ft) 
-ft_t ft;
-{
-	ft->info.size = WORD;
-	ft->info.style = SIGN2;
-	rawstartread(ft);
-	rawdefaults(ft);
-}
+STARTREAD(slstartread,DWORD,SIGN2) 
+STARTREAD(slstartwrite,DWORD,SIGN2) 
 
-void swstartwrite(ft) 
-ft_t ft;
-{
-	ft->info.size = WORD;
-	ft->info.style = SIGN2;
-	rawstartwrite(ft);
-	rawdefaults(ft);
-}
+STARTREAD(ulstartread,BYTE,ULAW) 
+STARTREAD(ulstartwrite,BYTE,ULAW) 
 
-void ulstartread(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = ULAW;
-	rawstartread(ft);
-	rawdefaults(ft);
-}
+STARTREAD(alstartread,BYTE,ALAW) 
+STARTREAD(alstartwrite,BYTE,ALAW) 
 
-void ulstartwrite(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = ULAW;
-	rawstartwrite(ft);
-	rawdefaults(ft);
-}
-
-void alstartread(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = ALAW;
-	rawstartread(ft);
-	rawdefaults(ft);
-}
-
-void alstartwrite(ft) 
-ft_t ft;
-{
-	ft->info.size = BYTE;
-	ft->info.style = ALAW;
-	rawstartwrite(ft);
-	rawdefaults(ft);
-}
-
 void rawdefaults(ft)
 ft_t ft;
 {
@@ -517,5 +465,4 @@
 	if (ft->info.channels == -1)
 		ft->info.channels = 1;
 }
-
 
--- a/src/resampl.h
+++ b/src/resampl.h
@@ -1,4 +1,3 @@
-
 /*
  * FILE: resample.h
  *   BY: Julius Smith (at CCRMA, Stanford U)
@@ -8,68 +7,55 @@
  * VERS: 2.0  (17-JUN-88, 3:00pm)
  */
 
-#define MAXNWING  5122
-#define MAXFACTOR 4       /* Maximum Factor without output buff overflow */
+/*
+ * October 29, 1999
+ * Various changes, bugfixes(?), increased precision, by Stan Brooks.
+ *
+ * This source code 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.
+ *
+ */
 
-
-
 /* Conversion constants */
-#define Nhc       8
-#define Na        7
-#define Np       (Nhc+Na)
-#define Npc      (1<<Nhc)
-#define Amask    ((1<<Na)-1)
-#define Pmask    ((1<<Np)-1)
-#define Nh       16
-#define Nb       16
-#define Nhxn     14
-#define Nhg      (Nh-Nhxn)
-#define NLpScl   13
+#define Lc        7
+#define Nc       (1<<Lc)
+#define La        16
+#define Na       (1<<La)
+#define Lp       (Lc+La)
+#define Np       (1<<Lp)
+#define Amask    (Na-1)
+#define Pmask    (Np-1)
 
+#define MAXNWING  (80<<Lc)
 /* Description of constants:
  *
- * Npc - is the number of look-up values available for the lowpass filter
+ * Nc - is the number of look-up values available for the lowpass filter
  *    between the beginning of its impulse response and the "cutoff time"
  *    of the filter.  The cutoff time is defined as the reciprocal of the
  *    lowpass-filter cut off frequence in Hz.  For example, if the
- *    lowpass filter were a sinc function, Npc would be the index of the
+ *    lowpass filter were a sinc function, Nc would be the index of the
  *    impulse-response lookup-table corresponding to the first zero-
  *    crossing of the sinc function.  (The inverse first zero-crossing
  *    time of a sinc function equals its nominal cutoff frequency in Hz.)
- *    Npc must be a power of 2 due to the details of the current
- *    implementation. The default value of 512 is sufficiently high that
+ *    Nc must be a power of 2 due to the details of the current
+ *    implementation. The default value of 128 is sufficiently high that
  *    using linear interpolation to fill in between the table entries
- *    gives approximately 16-bit accuracy in filter coefficients.
+ *    gives approximately 16-bit precision, and quadratic interpolation
+ *    gives about 23-bit (float) precision in filter coefficients.
  *
- * Nhc - is log base 2 of Npc.
+ * Lc - is log base 2 of Nc.
  *
- * Na - is the number of bits devoted to linear interpolation of the
+ * La - is the number of bits devoted to linear interpolation of the
  *    filter coefficients.
  *
- * Np - is Na + Nhc, the number of bits to the right of the binary point
+ * Lp - is La + Lc, the number of bits to the right of the binary point
  *    in the integer "time" variable. To the left of the point, it indexes
  *    the input array (X), and to the right, it is interpreted as a number
- *    between 0 and 1 sample of the input X.  Np must be less than 16 in
- *    this implementation.
+ *    between 0 and 1 sample of the input X.  The default value of 23 is
+ *    about right.  There is a constraint that the filter window must be
+ *    "addressable" in a LONG int, more precisely, if Nmult is the number
+ *    of sinc zero-crossings in the right wing of the filter window, then
+ *    (Nwing<<Lp) must be expressible in 31 bits.
  *
- * Nh - is the number of bits in the filter coefficients. The sum of Nh and
- *    the number of bits in the input data (typically 16) cannot exceed 32.
- *    Thus Nh should be 16.  The largest filter coefficient should nearly
- *    fill 16 bits (32767).
- *
- * Nb - is the number of bits in the input data. The sum of Nb and Nh cannot
- *    exceed 32.
- *
- * Nhxn - is the number of bits to right shift after multiplying each input
- *    sample times a filter coefficient. It can be as great as Nh and as
- *    small as 0. Nhxn = Nh-2 gives 2 guard bits in the multiply-add
- *    accumulation.  If Nhxn=0, the accumulation will soon overflow 32 bits.
- *
- * Nhg - is the number of guard bits in mpy-add accumulation (equal to Nh-Nhxn).
- *
- * NLpScl - is the number of bits allocated to the unity-gain normalization
- *    factor.  The output of the lowpass filter is multiplied by LpScl and
- *    then right-shifted NLpScl bits. To avoid overflow, we must have 
- *    Nb+Nhg+NLpScl < 32.
  */
-
--- a/src/resample.c
+++ b/src/resample.c
@@ -28,6 +28,16 @@
  * too low by 2 when downsampling.
  * Andreas Wilde, 12. Feb. 1999, andreas@eakaw2.et.tu-dresden.de
 */
+/*
+ * October 29, 1999
+ * Various changes, bugfixes(?), increased precision, by Stan Brooks.
+ *
+ * This source code 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.
+ *
+ */
+
 #include <math.h>
 #include <stdlib.h>
 #ifdef HAVE_MALLOC_H
@@ -39,67 +49,52 @@
 #include "resdefs.h"
 #include "resampl.h"
 
-#define IBUFFSIZE 4096                         /* Input buffer size */
-#define OBUFFSIZE (IBUFFSIZE*MAXFACTOR+2)      /* Calc'd out buffer size */
+#define Float double/*float*/
+#define ISCALE 0x10000
 
+#define BUFFSIZE 8192 /*16384*/               /* Total buffer size */
+#define L64 long long
+
 /* Private data for Lerp via LCM file */
 typedef struct resamplestuff {
-   double Factor;               /* Factor = Fout/Fin sample rates */
-   double rolloff;              /* roll-off frequency */
-   double beta;                 /* passband/stopband tuning magic */
-   short InterpFilt;      	/* TRUE means interpolate filter coeffs */
-   UHWORD Oskip;		/* number of bogus output samples at start */
-   UHWORD LpScl, Nmult, Nwing;
-   HWORD *Imp;         		/* impulse [MAXNWING] Filter coefficients */
-   HWORD *ImpD;        		/* [MAXNWING] ImpD[n] = Imp[n+1]-Imp[n] */
-   /* for resample main loop */
-   UWORD Time;                  /* Current time/pos in input sample */
-   UHWORD Xp, Xoff, Xread;
-   HWORD *X, *Y; 		/* I/O buffers */
+   double Factor;     /* Factor = Fout/Fin sample rates */
+   double rolloff;    /* roll-off frequency */
+   double beta;       /* passband/stopband tuning magic */
+   int quadr;         /* non-zero to use qprodUD quadratic interpolation */
+   LONG Nmult;
+   LONG Nwing;
+   LONG Nq;
+   Float *Imp;        /* impulse [Nwing+1] Filter coefficients */
+   double Time;       /* Current time/pos in input sample */
+   LONG dhb;
+   LONG Xh;           /* number of past/future samples needed by filter  */
+	 LONG Xoff;         /* Xh plus some room for creep  */
+   LONG Xread;        /* X[Xread] is start-position to enter new samples */
+   LONG Xp;           /* X[Xp] is position to start filter application   */
+	 LONG Xsize,Ysize;  /* size (Floats) of X[],Y[]         */
+   Float *X, *Y;      /* I/O buffers */
 } *resample_t;
 
-int makeFilter(P6(HWORD Imp[],
-		  HWORD ImpD[],
-		  UHWORD *LpScl,
-		  UHWORD Nwing,
+void LpFilter(P5(double c[],
+		LONG N,
+		double frq,
+		double Beta,
+		LONG Num));
+
+int makeFilter(P5(Float Imp[],
+		  LONG Nwing,
 		  double Froll,
-		  double Beta));
-HWORD SrcUp(P10(HWORD X[],
-		HWORD Y[],
-		double Factor,
-		UWORD *Time,
-		UHWORD Nx,
-		UHWORD Nwing,
-		UHWORD LpScl,
-		HWORD Imp[],
-		HWORD ImpD[],
-		BOOL Interp));
-HWORD SrcUD(P10(HWORD X[],
-		HWORD Y[],
-		double Factor,
-		UWORD *Time,
-		UHWORD Nx,
-		UHWORD Nwing,
-		UHWORD LpScl,
-		HWORD Imp[],
-		HWORD ImpD[],
-		BOOL Interp));
-IWORD FilterUp(P7(HWORD Imp[],
-		  HWORD ImpD[],
-		  UHWORD Nwing,
-		  BOOL Interp,
-		  HWORD *Xp,
-		  HWORD Ph,
-		  HWORD Inc));
-IWORD FilterUD(P8(HWORD Imp[],
-		  HWORD ImpD[],
-		  UHWORD Nwing,
-		  BOOL Interp,
-		  HWORD *Xp,
-		  HWORD Ph,
-		  HWORD Inc,
-		  UHWORD dhb));
+		  double Beta,
+		  LONG Num));
 
+static LONG SrcUD(P2(resample_t r, LONG Nx));
+
+
+#if 0
+static u_int32_t iprodC;
+static u_int32_t iprodM;
+#endif
+
 /*
  * Process options
  */
@@ -108,25 +103,48 @@
 int n;
 char **argv;
 {
-	resample_t resample = (resample_t) effp->priv;
+	resample_t r = (resample_t) effp->priv;
 
 	/* These defaults are conservative with respect to aliasing. */
-	resample->rolloff = 0.8;
-	resample->beta = 17.5;
+	r->rolloff = 0.8;
+	r->beta = 16; /* anything <=2 means Nutall window */
+	r->quadr = 0;
+	r->Nmult = 39;
 
 	/* This used to fail, but with sox-12.15 it works. AW */
-	if ((n >= 1) && !sscanf(argv[0], "%lf", &resample->rolloff))
-		fail("Usage: resample [ rolloff [ beta ] ]");
-	else if ((resample->rolloff < 0.01) || (resample->rolloff > 1.0))
-	    fail("resample: rolloff factor (%f) no good, should be 0.01<x<1.0", 
-			resample->rolloff);
-	if ((n >= 2) && !sscanf(argv[1], "%lf", &resample->beta))
-		fail("Usage: resample [ rolloff [ beta ] ]");
-	else if (resample->beta < 1.0)
-	        fail("resample: beta factor (%f) no good, should be >= 1.0", 
-			resample->beta);
-	report("resample opts: %f, %f\n", 
-		resample->rolloff, resample->beta);
+	if ((n >= 1)) {
+		if (!strcmp(argv[0], "-qs")) {
+			r->quadr = 1;
+			n--; argv++;
+		}
+		else if (!strcmp(argv[0], "-q")) {
+			r->rolloff = 0.9;
+			r->quadr = 1;
+			r->Nmult = 75;
+			n--; argv++;
+		}
+		else if (!strcmp(argv[0], "-ql")) {
+			r->rolloff = 0.9;
+			r->quadr = 1;
+			r->Nmult = 149;
+			n--; argv++;
+		}
+	}
+
+	if ((n >= 1) && !sscanf(argv[0], "%lf", &r->rolloff))
+	  fail("Usage: resample [ rolloff [ beta ] ]");
+	else if ((r->rolloff <= 0.01) || (r->rolloff >= 1.0))
+	  fail("resample: rolloff factor (%f) no good, should be 0.01<x<1.0", r->rolloff);
+
+	if ((n >= 2) && !sscanf(argv[1], "%lf", &r->beta))
+	  fail("Usage: resample [ rolloff [ beta ] ]");
+	else if (r->beta <= 2.0) {
+	  r->beta = 0;
+		report("resample opts: Nuttall window, cutoff %f\n", r->rolloff);
+	} else {
+		report("resample opts: Kaiser window, cutoff %f, beta %f\n", r->rolloff, r->beta);
+	}
+
 }
 
 /*
@@ -135,69 +153,63 @@
 void resample_start(effp)
 eff_t effp;
 {
-	resample_t resample = (resample_t) effp->priv;
+	resample_t r = (resample_t) effp->priv;
+	LONG Xoff;
 	int i;
-	
-	resample->InterpFilt = 1;	/* interpolate filter: slower */
-	resample->Factor = 
-		(double)effp->outinfo.rate / (double)effp->ininfo.rate;
-	
-	/* Check for illegal constants */
-	if (Np >= 16)
-		fail("Error: Np>=16");
-	if (Nb+Nhg+NLpScl >= 32)
-		fail("Error: Nb+Nhg+NLpScl>=32");
-	if (Nh+Nb > 32)
-	      fail("Error: Nh+Nb>32");
 
+	r->Factor = (double)effp->outinfo.rate / (double)effp->ininfo.rate;
 
-	resample->Imp = (HWORD *) malloc(sizeof(HWORD) * MAXNWING);
-	resample->ImpD = (HWORD *) malloc(sizeof(HWORD) * MAXNWING);
-	resample->X = (HWORD *) malloc(sizeof(HWORD) * IBUFFSIZE);
-	resample->Y = (HWORD *) malloc(sizeof(HWORD) * OBUFFSIZE);
+	r->Nq = Nc; /* for now */
 
-	/* upsampling requires smaller Nmults */
-	for(resample->Nmult = 37; resample->Nmult > 1; resample->Nmult -= 2) {
-		/* # of filter coeffs in right wing */
-		resample->Nwing = Npc*(resample->Nmult+1)/2;     
-		/* This prevents just missing last coeff */
-		/*   for integer conversion factors  */
-		resample->Nwing += Npc/2 + 1;      
+	/* Check for illegal constants */
+# if 0
+	if (Lp >= 16) fail("Error: Lp>=16");
+	if (Nb+Nhg+NLpScl >= 32) fail("Error: Nb+Nhg+NLpScl>=32");
+	if (Nh+Nb > 32) fail("Error: Nh+Nb>32");
+# endif
 
-		/* returns error # or 0 for success */
-		if (makeFilter(resample->Imp, resample->ImpD, 
-				&resample->LpScl, resample->Nwing, 
-				resample->rolloff, resample->beta))
-				continue;
-			else
-				break;
-			
-	}
+	/* Nwing: # of filter coeffs in right wing */
+	r->Nwing = r->Nq * (r->Nmult/2+1) + 1;
 
-	if(resample->Nmult == 1)
+	r->Imp = (Float *)malloc(sizeof(Float) * (r->Nwing+2)) + 1;
+	/* need Imp[-1] and Imp[Nwing] for quadratic interpolation */
+	/* returns error # <=0, or adjusted wing-len > 0 */
+	i = makeFilter(r->Imp, r->Nwing, r->rolloff, r->beta, r->Nq);
+	if (i <= 0)
 		fail("resample: Unable to make filter\n");
 
-	if (resample->Factor < 1)
-		resample->LpScl = resample->LpScl*resample->Factor + 0.5;
-	/* Calc reach of LP filter wing & give some creeping room */
-	resample->Xoff = ((resample->Nmult+1)/2.0) * 
-		MAX(1.0,1.0/resample->Factor) + 10;
-	if (IBUFFSIZE < 2*resample->Xoff)      /* Check input buffer size */
-		fail("IBUFFSIZE (or Factor) is too small");
+	report("Nmult: %ld, Nwing: %ld, Nq: %ld\n",r->Nmult,r->Nwing,r->Nq);
 
-	/* Current "now"-sample pointer for input */
-	resample->Xp = resample->Xoff;             
+	r->dhb = Np;  /* Fixed-point Filter sampling-time-increment */
+  if (r->Factor<1.0) r->dhb = r->Factor*Np + 0.5;
+  r->Xh = (r->Nwing<<La)/r->dhb;
+	/* (Xh * dhb)>>La is max index into Imp[] */
+
+	/* reach of LP filter wings + some creeping room */
+	Xoff = r->Xh + 10;
+	r->Xoff = Xoff;
+
+	/* Current "now"-sample pointer for input to filter */
+	r->Xp = Xoff;
 	/* Position in input array to read into */
-	resample->Xread = resample->Xoff;          
+	r->Xread = Xoff;
 	/* Current-time pointer for converter */
-	resample->Time = (resample->Xoff<<Np);     
+	r->Time = Xoff;
 
-	/* Set sample drop at beginning */
-	resample->Oskip = resample->Xread * resample->Factor;
+	i = BUFFSIZE - 2*Xoff;
+	if (i < r->Factor + 1.0/r->Factor)      /* Check input buffer size */
+		fail("Factor is too small or large for BUFFSIZE");
+	
+	r->Xsize = 2*Xoff + i/(1.0+r->Factor);
+	r->Ysize = BUFFSIZE - r->Xsize;
+	report("Xsize %d, Ysize %d, Xoff %d",r->Xsize,r->Ysize,r->Xoff);
 
-	/* Need Xoff zeros at begining of sample */
-	for (i=0; i<resample->Xoff; i++)
-		resample->X[i] = 0;
+	r->X = (Float *) malloc(sizeof(Float) * (BUFFSIZE));
+	r->Y = r->X + r->Xsize;
+
+	/* Need Xoff zeros at beginning of sample */
+	for (i=0; i<Xoff; i++)
+		r->X[i] = 0;
 }
 
 /*
@@ -210,89 +222,78 @@
 LONG *ibuf, *obuf;
 LONG *isamp, *osamp;
 {
-	resample_t resample = (resample_t) effp->priv;
-	LONG i, last, creep, Nout, Nx;
-	UHWORD Nproc;
+	resample_t r = (resample_t) effp->priv;
+	LONG i, last, Nout, Nx, Nproc;
 
 	/* constrain amount we actually process */
-	Nproc = IBUFFSIZE - resample->Xp;
-	if (Nproc * resample->Factor >= OBUFFSIZE)
-		Nproc = OBUFFSIZE / resample->Factor;
-	if (Nproc * resample->Factor >= *osamp)
-		Nproc = *osamp / resample->Factor;
-	
-	Nx = Nproc - resample->Xread;
+	//fprintf(stderr,"Xp %d, Xread %d, isamp %d, ",r->Xp, r->Xread,*isamp);
+
+	Nproc = r->Xsize - r->Xp;
+
+	i = MIN(r->Ysize, *osamp);
+	if (Nproc * r->Factor >= i)
+	  Nproc = i / r->Factor;
+
+	Nx = Nproc - r->Xread; /* space for right-wing future-data */
 	if (Nx <= 0)
-		fail("Nx negative: %d", Nx);
-	if (Nx > *isamp) {
+		fail("Nx not positive: %d", Nx);
+	if (Nx > *isamp)
 		Nx = *isamp;
+	//fprintf(stderr,"Nx %d\n",Nx);
+
+	if (ibuf == NULL) {
+		for(i = r->Xread; i < Nx + r->Xread  ; i++) 
+			r->X[i] = 0;
+	} else {
+		for(i = r->Xread; i < Nx + r->Xread  ; i++) 
+			r->X[i] = (Float)(*ibuf++)/ISCALE;
 	}
-	for(i = resample->Xread; i < Nx + resample->Xread  ; i++) 
-		resample->X[i] = RIGHT(*ibuf++ + 0x8000, 16);
 	last = i;
-	Nproc = last - (resample->Xoff * 2);
-	for(; i < last + resample->Xoff  ; i++) 
-		resample->X[i] = 0;
+	Nproc = last - r->Xoff - r->Xp;
 
-	/* If we're draining out a buffer tail, 
-	 * just do it next time or in drain.
-	 */
-	if ((Nx == *isamp) && (Nx <= resample->Xoff)) {
+	if (Nproc <= 0) {
 		/* fill in starting here next time */
-		resample->Xread = last;
+		r->Xread = last;
 		/* leave *isamp alone, we consumed it */
 		*osamp = 0;
 		return;
 	}
-
-
-        /* SrcUp() is faster if we can use it */
-	if (resample->Factor > 1)       /* Resample stuff in input buffer */
-	    Nout = SrcUp(resample->X, resample->Y,
-		resample->Factor, &resample->Time, Nproc,
-		resample->Nwing, resample->LpScl,
-		resample->Imp, resample->ImpD, 
-		resample->InterpFilt);      
-	else
-            Nout = SrcUD(resample->X, resample->Y,
-		resample->Factor, &resample->Time, Nproc,
-		resample->Nwing, resample->LpScl,
-		resample->Imp, resample->ImpD,
-		resample->InterpFilt);
-
+	Nout = SrcUD(r, Nproc);
+	//fprintf(stderr,"Nproc %d --> %d\n",Nproc,Nout);
 	/* Move converter Nproc samples back in time */
-	resample->Time -= (Nproc<<Np); 
-        /* Advance by number of samples processed */
-	resample->Xp += Nproc;
+	r->Time -= Nproc;
+	/* Advance by number of samples processed */
+	r->Xp += Nproc;
 	/* Calc time accumulation in Time */
-	creep = (resample->Time>>Np) - resample->Xoff; 
-	if (creep)
 	{
-		resample->Time -= (creep<<Np);   /* Remove time accumulation */
-		resample->Xp += creep;     /* and add it to read pointer */
+	  LONG creep = r->Time - r->Xoff; 
+	  if (creep)
+	  {
+	  	  r->Time -= creep;   /* Remove time accumulation   */
+	  	  r->Xp += creep;     /* and add it to read pointer */
+	  	  /* fprintf(stderr,"Nproc %ld, creep %ld\n",Nproc,creep); */
+	  }
 	}
 
+	{
+	LONG i,k;
 	/* Copy back portion of input signal that must be re-used */
-	for (i=0; i<last - resample->Xp + resample->Xoff; i++) 
-	    resample->X[i] = resample->X[i + resample->Xp - resample->Xoff];
+	k = r->Xp - r->Xoff;
+	//fprintf(stderr,"k %d, last %d\n",k,last);
+	for (i=0; i<last - k; i++) 
+	    r->X[i] = r->X[i+k];
 
 	/* Pos in input buff to read new data into */
-	resample->Xread = i;                 
-	resample->Xp = resample->Xoff;
+	r->Xread = i;                 
+	r->Xp = r->Xoff;
 
-	/* copy to output buffer, zero-filling beginning */
-	/* zero-fill to preserve length and loop points */
-	for(i = 0; i < resample->Oskip; i++) {
-		*obuf++ = 0;
-	}
-	for(i = resample->Oskip; i < Nout + resample->Oskip; i++) {
-		*obuf++ = LEFT(resample->Y[i], 16);
-	}
+	for(i=0; i < Nout; i++)
+		*obuf++ = r->Y[i] * ISCALE;
 
 	*isamp = Nx;
 	*osamp = Nout;
 
-	resample->Oskip = 0;
+	}
 }
 
 /*
@@ -300,46 +301,33 @@
  */
 void resample_drain(effp, obuf, osamp)
 eff_t effp;
-ULONG *obuf;
-ULONG *osamp;
+LONG *obuf;
+LONG *osamp;
 {
-	resample_t resample = (resample_t) effp->priv;
-	LONG i, Nout;
-	UHWORD Nx;
+	resample_t r = (resample_t) effp->priv;
+	LONG i, Nout, Nx;
 	
-	Nx = resample->Xread - resample->Xoff;
-	if (Nx <= resample->Xoff * 2) {
-		/* zero-fill end */
-		for(i = 0; i < resample->Xoff; i++)
-			*obuf++ = 0;
-		*osamp = resample->Xoff;
-		return;
-	}
+	//fprintf(stderr,"Xp %d, Xread %d  <--- DRAIN\n",r->Xp, r->Xread);
+	if (r->Xsize - r->Xread < r->Xoff)
+		fail("resample_drain: Problem!\n");
 
-	if (Nx * resample->Factor >= *osamp)
+	/* fill out end with Xoff zeros */
+	for(i = 0; i < r->Xoff; i++)
+		r->X[i + r->Xread] = 0;
+
+	Nx = r->Xread - r->Xp;
+
+	if (Nx * r->Factor >= *osamp)
 		fail("resample_drain: Overran output buffer!\n");
 
-	/* fill out end with zeros */
-	for(i = 0; i < resample->Xoff; i++)
-		resample->X[i + resample->Xread] = 0;
-        /* SrcUp() is faster if we can use it */
-	if (resample->Factor >= 1)       /* Resample stuff in input buffer */
-	    Nout = SrcUp(resample->X, resample->Y,
-		resample->Factor, &resample->Time, Nx,
-		resample->Nwing, resample->LpScl,
-		resample->Imp, resample->ImpD, 
-		resample->InterpFilt);      
-	else
-            Nout = SrcUD(resample->X, resample->Y,
-		resample->Factor, &resample->Time, Nx,
-		resample->Nwing, resample->LpScl,
-		resample->Imp, resample->ImpD,
-		resample->InterpFilt);
-	
-	for(i = resample->Oskip; i < Nout; i++) {
-		*obuf++ = LEFT(resample->Y[i], 16);
-	}
-	*osamp = Nout - resample->Oskip;
+	/* Resample stuff in input buffer */
+	Nout = SrcUD(r, Nx);
+	//fprintf(stderr,"Nproc %d --> %d\n",Nx,Nout);
+
+	for(i = 0; i < Nout; i++)
+		*obuf++ = r->Y[i] * ISCALE;
+
+	*osamp = Nout;
 }
 
 /*
@@ -349,160 +337,183 @@
 void resample_stop(effp)
 eff_t effp;
 {
-	resample_t resample = (resample_t) effp->priv;
+	resample_t r = (resample_t) effp->priv;
 	
-	free(resample->Imp);
-	free(resample->ImpD);
-	free(resample->X);
-	free(resample->Y);
+	free(r->Imp - 1);
+	free(r->X);
+	/* free(r->Y); Y is in same block starting at X */ 
+	/*report("iC %d, iM %d, ratio %d", iprodC, iprodM, iprodM/iprodC);*/
 }
 
-/* From resample:filters.c */
-
-/* Sampling rate up-conversion only subroutine;
- * Slightly faster than down-conversion;
- */
-HWORD SrcUp(X, Y, Factor, Time, Nx, Nwing, LpScl, Imp, ImpD, Interp)
-HWORD X[], Y[];
-double Factor;
-UWORD *Time;
-UHWORD Nx, Nwing, LpScl;
-HWORD Imp[], ImpD[];
-BOOL Interp;
+/* over 90% of CPU time spent in this iprodUD() function */
+/* quadratic interpolation */
+static double qprodUD(Imp, Xp, Inc, T0, dhb, ct)
+const Float Imp[], *Xp;
+LONG Inc, dhb, ct;
+double T0;
 {
-   HWORD *Xp, *Ystart;
-   IWORD v;
+  const double f = 1.0/(1<<La);
+  double v;
+  LONG Ho;
 
-   double dt;                  /* Step through input signal */ 
-   UWORD dtb;                  /* Fixed-point version of Dt */
-   UWORD endTime;              /* When Time reaches EndTime, return to user */
+	Ho = T0 * dhb;
+	Ho += (ct-1)*dhb; /* so Float sum starts with smallest coef's */
+	Xp += (ct-1)*Inc;
+	v = 0;
+  do {
+    Float coef;
+    LONG Hoh;
+    Hoh = Ho>>La;
+		coef = Imp[Hoh];
+    {
+      Float dm,dp,t;
+      dm = coef - Imp[Hoh-1];
+      dp = Imp[Hoh+1] - coef;
+      t =(Ho & Amask) * f;
+      coef += ((dp-dm)*t + (dp+dm))*t*0.5;
+    }
+    /* filter coef, lower La bits by quadratic interpolation */
+    v += coef * *Xp;   /* sum coeff * input sample */
+    Xp -= Inc;     /* Input signal step. NO CHECK ON ARRAY BOUNDS */
+    Ho -= dhb;     /* IR step */
+  } while(--ct);
+  return v;
+}
 
-   dt = 1.0/Factor;            /* Output sampling period */
-   dtb = dt*(1<<Np) + 0.5;     /* Fixed-point representation */
+/* linear interpolation */
+static double iprodUD(Imp, Xp, Inc, T0, dhb, ct)
+const Float Imp[], *Xp;
+LONG Inc, dhb, ct;
+double T0;
+{
+  const double f = 1.0/(1<<La);
+  double v;
+  LONG Ho;
 
-   Ystart = Y;
-   endTime = *Time + (1<<Np)*(IWORD)Nx;
-   while (*Time < endTime)
-      {
-      Xp = &X[*Time>>Np];      /* Ptr to current input sample */
-      v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask),
-         -1);                  /* Perform left-wing inner product */
-      v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask),
-         1);                   /* Perform right-wing inner product */
-      v >>= Nhg;               /* Make guard bits */
-      v *= LpScl;              /* Normalize for unity filter gain */
-      *Y++ = v>>NLpScl;        /* Deposit output */
-      *Time += dtb;            /* Move to next sample by time increment */
-      }
-   return (Y - Ystart);        /* Return the number of output samples */
+  Ho = T0 * dhb;
+	Ho += (ct-1)*dhb; /* so Float sum starts with smallest coef's */
+  Xp += (ct-1)*Inc;
+	v = 0;
+  do {
+    Float coef;
+    LONG Hoh;
+    Hoh = Ho>>La;
+    /* if (Hoh >= End) break; */
+    coef = Imp[Hoh] + (Imp[Hoh+1]-Imp[Hoh]) * (Ho & Amask) * f;
+    /* filter coef, lower La bits by linear interpolation */
+    v += coef * *Xp;   /* sum coeff * input sample */
+    Xp -= Inc;     /* Input signal step. NO CHECK ON ARRAY BOUNDS */
+    Ho -= dhb;     /* IR step */
+  } while(--ct);
+  return v;
 }
 
-
+/* From resample:filters.c */
 /* Sampling rate conversion subroutine */
 
-HWORD SrcUD(X, Y, Factor, Time, Nx, Nwing, LpScl, Imp, ImpD, Interp)
-HWORD X[], Y[];
-double Factor;
-UWORD *Time;
-UHWORD Nx, Nwing, LpScl;
-HWORD Imp[], ImpD[];
-BOOL Interp;
+static LONG SrcUD(r, Nx)
+resample_t r;
+LONG Nx;
 {
-   HWORD *Xp, *Ystart;
-   IWORD v;
-
-   double dh;                  /* Step through filter impulse response */
+   Float *Ystart, *Y;
+   double Factor;
    double dt;                  /* Step through input signal */
-   UWORD endTime;              /* When Time reaches EndTime, return to user */
-   UWORD dhb, dtb;             /* Fixed-point versions of Dh,Dt */
+   double time;
+   double (*prodUD)();
+   int n;
 
-   dt = 1.0/Factor;            /* Output sampling period */
-   dtb = dt*(1<<Np) + 0.5;     /* Fixed-point representation */
+   prodUD = (r->quadr)? qprodUD:iprodUD; /* quadratic or linear interp */
+   Factor = r->Factor;
+   time = r->Time;
+   dt = 1.0/Factor;        /* Output sampling period */
+   /*fprintf(stderr,"Factor %f, dt %f, ",Factor,dt); */
+   /*fprintf(stderr,"Time %f, ",r->Time);*/
+	 /* (Xh * dhb)>>La is max index into Imp[] */
+	 /*fprintf(stderr,"ct=%d\n",ct);*/
+   /*fprintf(stderr,"ct=%.2f %d\n",(double)r->Nwing*Na/r->dhb, r->Xh);*/
+   Ystart = Y = r->Y;
+   n = (int)ceil((double)Nx/dt);
+   while(n--)
+      {
+      Float *Xp;
+      double v;
+      double T;
+      T = time-floor(time);        /* fractional part of Time */
+			Xp = r->X + (LONG)time;      /* Ptr to current input sample */
 
-   dh = MIN(Npc, Factor*Npc);  /* Filter sampling period */
-   dhb = dh*(1<<Na) + 0.5;     /* Fixed-point representation */
+      /* Past  inner product: */
+      v = (*prodUD)(r->Imp, Xp, -1, T, r->dhb, r->Xh); /* needs Np*Nmult in 31 bits */
+      /* Future inner product: */
+      v += (*prodUD)(r->Imp, Xp+1, 1, (1.0-T), r->dhb, r->Xh); /* prefer even total */
 
-   Ystart = Y;
-   endTime = *Time + (1<<Np)*(IWORD)Nx;
-   while (*Time < endTime)
-      {
-      Xp = &X[*Time>>Np];      /* Ptr to current input sample */
-      v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask),
-          -1, dhb);            /* Perform left-wing inner product */
-      v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask),
-           1, dhb);            /* Perform right-wing inner product */
-      v >>= Nhg;               /* Make guard bits */
-      v *= LpScl;              /* Normalize for unity filter gain */
-      *Y++ = v>>NLpScl;        /* Deposit output */
-      *Time += dtb;            /* Move to next sample by time increment */
+      if (Factor < 1) v *= Factor;
+      *Y++ = v;              /* Deposit output */
+      time += dt;            /* Move to next sample by time increment */
       }
+   r->Time = time;
+   /*fprintf(stderr,"Time %f\n",r->Time);*/
    return (Y - Ystart);        /* Return the number of output samples */
 }
 
-void LpFilter();
-
-int makeFilter(Imp, ImpD, LpScl, Nwing, Froll, Beta)
-HWORD Imp[], ImpD[];
-UHWORD *LpScl, Nwing;
+int makeFilter(Imp, Nwing, Froll, Beta, Num)
+Float Imp[];
+LONG Nwing, Num;
 double Froll, Beta;
 {
-   double DCgain, Scl, Maxh;
+   double DCgain;
    double *ImpR;
-   HWORD Dh;
-   LONG i, temp;
+   LONG Mwing, Dh, i;
 
    if (Nwing > MAXNWING)                      /* Check for valid parameters */
-      return(1);
+      return(-1);
    if ((Froll<=0) || (Froll>1))
-      return(2);
-   if (Beta < 1)
-      return(3);
+      return(-2);
 
-   ImpR = (double *) malloc(sizeof(double) * MAXNWING);
-   LpFilter(ImpR, (int)Nwing, Froll, Beta, Npc); /* Design a Kaiser-window */
-                                                 /* Sinc low-pass filter */
+   /* 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);
 
-   /* Compute the DC gain of the lowpass filter, and its maximum coefficient
-    * magnitude. Scale the coefficients so that the maximum coeffiecient just
-    * fits in Nh-bit fixed-point, and compute LpScl as the NLpScl-bit (signed)
-    * scale factor which when multiplied by the output of the lowpass filter
-    * gives unity gain. */
+   ImpR = (double *) malloc(sizeof(double) * Mwing);
+
+   /* Design a Nuttall or Kaiser windowed Sinc low-pass filter */
+   LpFilter(ImpR, Mwing, Froll, Beta, Num);
+
+   /* 'correct' the DC gain of the lowpass filter */
    DCgain = 0;
-   Dh = Npc;                       /* Filter sampling period for factors>=1 */
-   for (i=Dh; i<Nwing; i+=Dh)
+   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 */
+   report("DCgain err=%.12f",DCgain-1.0);
 
-   for (Maxh=i=0; i<Nwing; i++)
-      Maxh = MAX(Maxh, fabs(ImpR[i]));
+   for (i=0; i<Mwing; i++) {
+      Imp[i] = ImpR[i]/DCgain;
+   }
+   free(ImpR);
+   for (i=Mwing; i<=Nwing; i++) Imp[i] = 0;
+	 /* Imp[Nwing] and Imp[-1] needed for quadratic interpolation */
+   Imp[-1] = Imp[1];
 
-   Scl = ((1<<(Nh-1))-1)/Maxh;     /* Map largest coeff to 16-bit maximum */
-   temp = fabs((1<<(NLpScl+Nh))/(DCgain*Scl));
-   if (temp >= (1L<<16)) {
-      free(ImpR);
-      return(4);                   /* Filter scale factor overflows UHWORD */
-    }
-   *LpScl = temp;
+#  if 0
+   {
+      double v = 0;
+      int s=-1;
+      for (i=Num; i<Mwing; i+=Num, s=-s)
+      v += s*Imp[i];
+      report("NYQgain %.12f vs %.12f",Imp[0], -2*v);
+      v = -2*v - Imp[0];
+      v *= (double)Nc/(double)(2*Mwing+1);
+      for (i=0; i<Mwing; i++)
+          Imp[i] += v*cos(M_PI*i/Nc);
 
-   /* Scale filter coefficients for Nh bits and convert to integer */
-   if (ImpR[0] < 0)                /* Need pos 1st value for LpScl storage */
-      Scl = -Scl;
-   for (i=0; i<Nwing; i++)         /* Scale them */
-      ImpR[i] *= Scl;
-   for (i=0; i<Nwing; i++)         /* Round them */
-      Imp[i] = ImpR[i] + 0.5;
-
-   /* ImpD makes linear interpolation of the filter coefficients faster */
-   for (i=0; i<Nwing-1; i++)
-      ImpD[i] = Imp[i+1] - Imp[i];
-   ImpD[Nwing-1] = - Imp[Nwing-1];      /* Last coeff. not interpolated */
-
-   free(ImpR);
-   return(0);
+   }
+#  endif
+   
+   return(Mwing);
 }
 
-
-
 /* LpFilter()
  *
  * reference: "Digital Filters, 2nd edition"
@@ -557,123 +568,33 @@
       temp *= temp;
       u *= temp;
       sum += u;
-      } while (u >= IzeroEPSILON*sum);
+   } while (u >= IzeroEPSILON*sum);
    return(sum);
 }
 
-
 void LpFilter(c,N,frq,Beta,Num)
 double c[], frq, Beta;
-int N, Num;
+LONG N, Num;
 {
-   double IBeta, temp;
-   int i;
+   LONG i;
 
    /* Calculate filter coeffs: */
    c[0] = frq;
-   for (i=1; i<N; i++)
-      {
-      temp = PI*(double)i/(double)Num;
-      c[i] = sin(temp*frq)/temp;
+   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/Izero(Beta);
+      for (i=1; i<N; i++) {
+         double x = (double)i / (double)(N);
+         c[i] *= Izero(Beta*sqrt(1.0-x*x)) * IBeta;
       }
-
-   /* Calculate and Apply Kaiser window to filter coeffs: */
-   IBeta = 1.0/Izero(Beta);
-   for (i=1; i<N; i++)
-      {
-      temp = (double)i / ((double)N * (double)1.0);
-      c[i] *= Izero(Beta*sqrt(1.0-temp*temp)) * IBeta;
+   } else { /* Apply Nuttall window: */
+      for(i = 0; i < N; i++) {
+         double x = M_PI*i / N;
+         c[i] *= 0.36335819 + 0.4891775*cos(x) + 0.1365995*cos(2*x) + 0.0106411*cos(3*x);
       }
+   }
 }
-
-
-
-
-IWORD FilterUp(Imp, ImpD, Nwing, Interp, Xp, Ph, Inc)
-HWORD Imp[], ImpD[];
-UHWORD Nwing;
-BOOL Interp;
-HWORD *Xp, Ph, Inc;
-{
-   HWORD a=0, *Hp, *Hdp=0, *End;
-   IWORD v, t;
-
-   v=0;
-   Hp = &Imp[Ph>>Na];
-   End = &Imp[Nwing];
-   if (Interp)
-      {
-      Hdp = &ImpD[Ph>>Na];
-      a = Ph & Amask;
-      }
-   /* Possible Bug: Hdp and a are not initialized if Interp == 0 */
-   if (Inc == 1)                     /* If doing right wing...              */
-      {                              /* ...drop extra coeff, so when Ph is  */
-      End--;                         /*    0.5, we don't do too many mult's */
-      if (Ph == 0)                   /* If the phase is zero...           */
-         {                           /* ...then we've already skipped the */
-         Hp += Npc;                  /*    first sample, so we must also  */
-         Hdp += Npc;                 /*    skip ahead in Imp[] and ImpD[] */
-         }
-      }
-   while (Hp < End)
-      {
-      t = *Hp;                       /* Get filter coeff */
-      if (Interp)
-         {
-         t += (((IWORD)*Hdp)*a)>>Na;  /* t is now interp'd filter coeff */
-         Hdp += Npc;                 /* Filter coeff differences step */
-	 }
-      t *= *Xp;      /* Mult coeff by input sample */
-	  if (t & (1<<(Nhxn-1)))  /* Round, if needed */
-		 t += (1<<(Nhxn-1));
-      t >>= Nhxn;    /* Leave some guard bits, but come back some */
-      v += t;        /* The filter output */
-      Hp += Npc;     /* Filter coeff step */
-      Xp += Inc;     /* Input signal step. NO CHECK ON ARRAY BOUNDS */
-      }
-   return(v);
-}
-
-
-IWORD FilterUD(Imp, ImpD, Nwing, Interp, Xp, Ph, Inc, dhb)
-HWORD Imp[], ImpD[];
-UHWORD Nwing;
-BOOL Interp;
-HWORD *Xp, Ph, Inc;
-UHWORD dhb;
-{
-   HWORD a, *Hp, *Hdp, *End;
-   IWORD v, t;
-   UWORD Ho;
-
-   v=0;
-   Ho = (Ph*(UWORD)dhb)>>Np;
-   End = &Imp[Nwing];
-   if (Inc == 1)                     /* If doing right wing...              */
-      {                              /* ...drop extra coeff, so when Ph is  */
-      End--;                         /*    0.5, we don't do too many mult's */
-      if (Ph == 0)                   /* If the phase is zero...           */
-         Ho += dhb;                  /* ...then we've already skipped the */
-      }                              /*    first sample, so we must also  */
-                                     /*    skip ahead in Imp[] and ImpD[] */
-   while ((Hp = &Imp[Ho>>Na]) < End)
-      {
-      t = *Hp;       /* Get IR sample */
-      if (Interp)
-         {
-         Hdp = &ImpD[Ho>>Na]; /* get interp (lower Na) bits from diff table */
-         a = Ho & Amask;                  /* a is logically between 0 and 1 */
-         t += (((IWORD)*Hdp)*a)>>Na;      /* t is now interp'd filter coeff */
-	 }
-      t *= *Xp;      /* Mult coeff by input sample */
-	  if (t & (1<<(Nhxn-1)))  /* Round, if needed */
-		 t += (1<<(Nhxn-1));
-      t >>= Nhxn;    /* Leave some guard bits, but come back some */
-      v += t;        /* The filter output */
-      Ho += dhb;     /* IR step */
-      Xp += Inc;     /* Input signal step. NO CHECK ON ARRAY BOUNDS */
-      }
-   return(v);
-}
-
--- a/src/sox.c
+++ b/src/sox.c
@@ -556,7 +556,7 @@
 int flow_effect(e)
 int e;
 {
-    LONG i, idone, odone, idonel, odonel, idoner, odoner;
+    LONG i, done, idone, odone, idonel, odonel, idoner, odoner;
     LONG *ibuf, *obuf;
 
     /* I have no input data ? */
@@ -575,6 +575,7 @@
 	efftab[e-1].odone += idone;
 	efftab[e].odone = 0;
 	efftab[e].olen = odone;
+	done = idone + odone;
     } else {
 	
 	/* Put stereo data in two seperate buffers and run effect
@@ -609,9 +610,10 @@
 	efftab[e-1].odone += idonel + idoner;
 	efftab[e].odone = 0;
 	efftab[e].olen = odonel + odoner;
+	done = idonel + idoner + odonel + odoner;
     } 
-    if (idone == 0) 
-	fail("Effect took no samples!");
+    if (done == 0) 
+	fail("Effect took & gave no samples!");
     return 1;
 }
 
--- a/src/stat.c
+++ b/src/stat.c
@@ -15,20 +15,24 @@
  * No output.
  */
 
+#include <math.h>
 #include "st.h"
 
+#define MAXLONG 0x7fffffffL
+
 /* Private data for STAT effect */
 typedef struct statstuff {
-	LONG	min, max, mean;		/* amplitudes */
-	LONG	dmin, dmax, dmean;	/* deltas */
-	LONG	last;			/* previous sample */
+	double	min, max, asum, sum1, sum2;		/* amplitudes */
+	double	dmin, dmax, dsum1, dsum2;	/* deltas */
+	double	scale;			/* scale-factor    */
+	double	last;			/* previous sample */
+	double	read;
 	int	first;
-	int	total;
 	int	volume;
-        ULONG   bin[4];
+	int	srms;
+	ULONG   bin[4];
 } *stat_t;
 
-#define	abs(val)	(((val) < 0) ? -(val) : (val))
 
 /*
  * Process options
@@ -40,15 +44,44 @@
 {
 	stat_t stat = (stat_t) effp->priv;
 
+	stat->scale = MAXLONG;
 	stat->volume = 0;
-	if (n)
+	stat->srms = 0;
+	while (n>0)
 	{
-		if (!(strcmp(argv[0], "-v")))
+		if (!(strcmp(argv[0], "-v"))) {
 			stat->volume = 1;
-		else if (!(strcmp(argv[0], "debug")))
+			goto did1;
+		}
+		if (!(strcmp(argv[0], "-s"))) {
+			double scale;
+
+			if (n <= 1) 
+			  fail("-s option: invalid argument");
+			if (!strcmp(argv[1],"rms")) {
+				stat->srms=1;
+				goto did2;
+			}
+			if (!sscanf(argv[1], "%lf", &scale))
+			  fail("-s option: invalid argument");
+			stat->scale = scale;
+			goto did2;
+		}
+		if (!(strcmp(argv[0], "-rms"))) {
+			double scale;
+			if (n <= 1 || !sscanf(argv[1], "%lf", &scale))
+			  fail("-s option expects float argument");
+			stat->srms = 1;
+			goto did2;
+		}
+		if (!(strcmp(argv[0], "debug"))) {
 			stat->volume = 2;
+			goto did1;
+		}
 		else
-			fail("Summary effect only allows debug or -v as options.");
+			fail("Summary effect: unknown option");
+	  did2: --n; ++argv;
+	  did1: --n; ++argv;
 	}
 }
 
@@ -59,12 +92,18 @@
 eff_t effp;
 {
 	stat_t stat = (stat_t) effp->priv;
-        int i;
+	int i;
 
-	stat->min = stat->dmin = 0x7fffffffL;
-	stat->max = stat->dmax = 0x80000000L;
 	stat->first = 1;
+	stat->min = stat->max = 0;
+	stat->asum = 0;
+	stat->sum1 = stat->sum2 = 0;
 
+	stat->dmin = stat->dmax = 0;
+	stat->dsum1 = stat->dsum2 = 0;
+
+	stat->read = 0;
+
 	for (i = 0; i < 4; i++)
 		stat->bin[i] = 0;
 
@@ -82,7 +121,7 @@
 {
 	stat_t stat = (stat_t) effp->priv;
 	int len, done;
-	LONG samp, delta;
+	double samp, delta;
 	short count;
 
 	count = 0;
@@ -89,54 +128,46 @@
 	len = ((*isamp > *osamp) ? *osamp : *isamp);
 	for(done = 0; done < len; done++) {
 		/* work in absolute levels for both sample and delta */
-		samp = *ibuf++;
-	        *obuf++ = samp;
+		samp = (*ibuf)/stat->scale;
+    stat->bin[RIGHT(*ibuf,30)+2]++;
+		*obuf++ = *ibuf++;
 
 		if (stat->volume == 2)
 		{
-#ifdef __alpha__
-		    fprintf(stderr,"%8x ",samp);
-#else
-		    fprintf(stderr,"%8lx ",samp);
-#endif
+		    fprintf(stderr,"%f ",samp);
 		    if (count++ == 5)
 		    {
-		        fprintf(stderr,"\n");
-			count = 0;
+				fprintf(stderr,"\n");
+				count = 0;
 		    }
 		}
 
-                stat->bin[RIGHT(samp,30)+2]++;
 
-		samp = abs(samp);
-		if (samp < stat->min)
-			stat->min = samp;
-		if (samp > stat->max)
-			stat->max = samp;
 		if (stat->first) {
+			stat->min = stat->max = samp;
 			stat->first = 0;
-			stat->mean = samp;
-			stat->dmean = 0;
-		} else  {
-			/* overflow avoidance */
-			if ((stat->mean > 0x20000000L) || (samp > 0x20000000L))
-				stat->mean = stat->mean/2 + samp/2;
-			else
-				stat->mean = (stat->mean + samp)/2;
-
-			delta = abs(samp - stat->last);
-			if (delta < stat->dmin)
-				stat->dmin = delta;
-			if (delta > stat->dmax)
-				stat->dmax = delta;
-			/* overflow avoidance */
-			if ((delta > 0x20000000L) || (stat->dmean > 0x20000000L))
-				stat->dmean = stat->dmean/2 + delta/2;
-			else
-				stat->dmean = (stat->dmean + delta)/2;
 		}
+		if (stat->min > samp)
+			stat->min = samp;
+		else if (stat->max < samp)
+			stat->max = samp;
+
+		stat->sum1 += samp;
+		stat->sum2 += samp*samp;
+		stat->asum += fabs(samp);
+		
+		delta = fabs(samp - stat->last);
+		if (delta < stat->dmin)
+			stat->dmin = delta;
+		else if (delta > stat->dmax)
+			stat->dmax = delta;
+
+		stat->dsum1 += delta;
+		stat->dsum2 += delta*delta;
+
 		stat->last = samp;
 	}
+	stat->read += len;
 	/* Process all samples */
 }
 
@@ -149,39 +180,61 @@
 eff_t effp;
 {
 	stat_t stat = (stat_t) effp->priv;
-	double amp, range;
-        float x;
+	double amp, scale, srms, freq;
+	double x, ct;
 
-	stat->min   = RIGHT(stat->min, 16);
-	stat->max   = RIGHT(stat->max, 16);
-	stat->mean  = RIGHT(stat->mean, 16);
-	stat->dmin  = RIGHT(stat->dmin, 16);
-	stat->dmax  = RIGHT(stat->dmax, 16);
-	stat->dmean = RIGHT(stat->dmean, 16);
+	ct = stat->read;
 
-	range = 32767.0;
+	if (stat->srms) {
+		double f;
+		srms = sqrt(stat->sum2/ct);
+		f = 1.0/srms;
+		stat->max *= f;
+		stat->min *= f;
+		stat->asum *= f;
+		stat->sum1 *= f;
+		stat->sum2 *= f*f;
+		stat->dmax *= f;
+		stat->dmin *= f;
+		stat->dsum1 *= f;
+		stat->dsum2 *= f*f;
+		stat->scale *= srms;
+	}
 
-	amp = - stat->min;
+	scale = stat->scale;
+
+	amp = -stat->min;
 	if (amp < stat->max)
 		amp = stat->max;
+
 	/* Just print the volume adjustment */
-	if (stat->volume == 1) {
-		fprintf(stderr, "%.3f\n", 32767.0/amp);
+	if (stat->volume == 1 && amp > 0) {
+		fprintf(stderr, "%.3f\n", MAXLONG/(amp*scale));
 		return;
 	}
-	else if (stat->volume == 2) {
+	if (stat->volume == 2) {
 		fprintf(stderr, "\n");
 	}
 	/* print them out */
-	fprintf(stderr, "Maximum amplitude: %.3f\n", stat->max/range);
-	fprintf(stderr, "Minimum amplitude: %.3f\n", stat->min/range);
-	fprintf(stderr, "Mean    amplitude: %.3f\n", stat->mean/range);
+	fprintf(stderr, "Samples read:      %12lu\n", (unsigned long)ct);
+	if (stat->srms)
+		fprintf(stderr, "Scaled by rms:     %12.6f\n", srms);
+	else
+		fprintf(stderr, "Scaled by:         %12.1f\n", scale);
+	fprintf(stderr, "Maximum amplitude: %12.6f\n", stat->max);
+	fprintf(stderr, "Minimum amplitude: %12.6f\n", stat->min);
+	fprintf(stderr, "Mean    norm:      %12.6f\n", stat->asum/ct);
+	fprintf(stderr, "Mean    amplitude: %12.6f\n", stat->sum1/ct);
+	fprintf(stderr, "RMS     amplitude: %12.6f\n", sqrt(stat->sum2/ct));
 
-	fprintf(stderr, "Maximum delta:     %.3f\n", stat->dmax/range);
-	fprintf(stderr, "Minimum delta:     %.3f\n", stat->dmin/range);
-	fprintf(stderr, "Mean    delta:     %.3f\n", stat->dmean/range);
+	fprintf(stderr, "Maximum delta:     %12.6f\n", stat->dmax);
+	fprintf(stderr, "Minimum delta:     %12.6f\n", stat->dmin);
+	fprintf(stderr, "Mean    delta:     %12.6f\n", stat->dsum1/ct);
+	fprintf(stderr, "RMS     delta:     %12.6f\n", sqrt(stat->dsum2/ct));
+	freq = sqrt(stat->dsum2/stat->sum2)*effp->ininfo.rate/(M_PI*2);
+	fprintf(stderr, "Rough   frequency: %12d\n", (int)freq);
 
-	fprintf(stderr, "Volume adjustment: %.3f\n", 32767.0/amp);
+	if (amp>0) fprintf(stderr, "Volume adjustment: %12.3f\n", MAXLONG/(amp*scale));
 
         if (stat->bin[2] == 0 && stat->bin[3] == 0)
                 fprintf(stderr, "\nProbably text, not sound\n");
@@ -190,22 +243,36 @@
                 x = (float)(stat->bin[0] + stat->bin[3]) / (float)(stat->bin[1] + stat->bin[2]);
 
                 if (x >= 3.0)                        /* use opposite style */
+		{
                         if (effp->ininfo.style == UNSIGNED)
+			{
                                 printf ("\nTry: -t raw -b -s \n");
+			}
                         else
+			{
                                 printf ("\nTry: -t raw -b -u \n");
+			}
 
-                else if (x <= 1.0/3.0);              /* correctly decoded */
-
+		}
+                else if (x <= 1.0/3.0)
+		{ 
+		    ;;              /* correctly decoded */
+		}
                 else if (x >= 0.5 && x <= 2.0)       /* use ULAW */
+		{
                         if (effp->ininfo.style == ULAW)
+			{
                                 printf ("\nTry: -t raw -b -u \n");
+			}
                         else
+			{
                                 printf ("\nTry: -t raw -b -U \n");
-
+			}
+		}
                 else    
+		{
                         fprintf (stderr, "\nCan't guess the type\n");
+		}
         }
 
 }
-
--- a/tests.com
+++ /dev/null
@@ -1,41 +1,0 @@
-$   FVER = 'F$VERIFY(0)'
-$ !
-$ ! test files
-$ ! SOX Test script.  This should run without access violating or printing
-$ ! any messages.
-$ !
-$ ! VMS translation of tests.shr
-$ !
-$ ! Modification History
-$ ! 14 Dec 1992, K. S. Kubo, Created
-$ !
-$ ! NOTES:
-$ !	Does not support the voc test w/o checksum and rate byte.
-$ !
-$   FILE 	= "monkey"
-$   PROC_PATH	= F$Environment("PROCEDURE")
-$   SOX		= "$ " + F$Parse(PROC_PATH,,,"DEVICE") + -
-	F$Parse(PROC_PATH,,,"DIRECTORY") + "SOX"
-$ !
-$ ! verbose option -- uncomment the following line
-$ ! SOX		= SOX + " ""-V"""
-$ !
-$   ON ERROR THEN GOTO COM_EXIT
-$   ON SEVERE THEN GOTO COM_EXIT
-$   ON WARNING THEN CONTINUE
-$   DELETE/NOLOG ub.raw;*, sb.raw;*, ub2.raw;*, ub2.voc;*, ub.au;*, ub2.sf;*
-$   SOX 'FILE'.voc ub.raw
-$   SOX -t raw -r 8196 -u -b -c 1 ub.raw -r 8196 -s -b sb.raw
-$   SOX -t raw -r 8196 -s -b -c 1 sb.raw -r 8196 -u -b ub2.raw
-$   SOX -r 8196 -u -b -c 1 ub2.raw -r 8196 ub2.voc 
-$   DIFF/MODE=HEX ub.raw ub2.raw
-$   DELETE/NOLOG ub.raw;*, sb.raw;*, ub2.raw;*, ub2.voc;*
-$   SOX 'FILE'.au -u -r 8192 -u -b ub.raw
-$   SOX -r 8192 -u -b ub.raw -U -b ub.au 
-$   SOX ub.au -u ub2.raw 
-$   SOX ub.au -w ub2.sf
-$   DELETE/NOLOG ub.raw;*, ub.au;*, ub2.raw;*, ub2.sf;*
-$ !
-$ COM_EXIT:
-$   FVER = F$VERIFY('FVER')
-$   EXIT
--- a/vms.lis
+++ /dev/null
@@ -1,65 +1,0 @@
-VAX/VMS port of SOX, release 5, patchlevel 7
-
-As an important side note, the DECsound tool only recognizes DDIF and Sun .au
-format sounds (Sun .au sounds *must* be uLaw, 8000Hz sampling rate to be
-readable).
-
-The portmeister makes no representations about the suitability of this
-software for any purpose.  This software is provided "as is" without
-warranties expressed or implied.
-
-New files:
-
-	sox.opt	- linker options file
-	descrip.mms - MMS description file
-	sound2au.com - VMS DCL command file to translate a sound to a Sun .au
-	    by way of sound2sun
-	sound2sun.c - program to convert sampled audio files to uLAW format
-	    (by Rich Gopstein and Harris Corporation)
-	sound2sun.opt - options file for sound2sun
-	tests.com - VMS DCL command file equivalent of tests.sh
-
-Modified files:
-
-	st.h -
-		added VMS definitions for READBINARY and WRITEBINARY
-		changed "#ifdef SYSV" to "#if defined(SYSV) || defined(VMS)"
-		    to pick up definitions of index, rindex, and bcopy
-		added definitions of macros IMPORT and EXPORT (used on VMS
-		    for variable scope) -- collateral damage affects variables
-		    formats, informat, outformat, sizes, styles, effects
-	wav.c -
-		changed extern to IMPORT for volume, amplitude, summary, and 
-		    verbose
-	voc.c -
-		changed extern to IMPORT for summary and verbose
-	sox.c -
-		replaced "extern errno" with "#include <errno.h>"
-		replaced "extern sys_errlist[]| with "#include <perror.h>"
-		added EXPORT to verbose, summary, volume, amplitdue, 
-		    informat, outformat, and writing
-		removed unneeded extern declaration of formats[] (already
-		    defined in st.h)
-	sndrtool.c -
-		replaced "extern errno" with "#include <errno.h>"
-		replaced "extern sys_errlist[]| with "#include <perror.h>"
-	skel.c -
-		changed extern to IMPORT for volume, amplitude, summary, and 
-		    verbose
-	sf.c -
-		changed extern to IMPORT for summary and verbose
-	sbdsp.c -
-		changed extern to IMPORT for volume, amplitude, summary, and 
-		    verbose
-	raw.c -
-		changed extern to IMPORT for summary and verbose
-	misc.c -
-		moved "#include st.h" to top of file
-		added EXPORT to sizes[] and styles[]
-	handlers.c -
-		added EXPORT to effects[] and formats[]
-	echo.c -
-		changed extern to IMPORT for writing
-	8svx.c -
-		replaced "extern errno" with "#include <errno.h>"
-		replaced "extern sys_errlist[]| with "#include <perror.h>"