Here is some software to convert between 44.1 and 48 KHz rates.

Theory of operation:
44.1 and 48 are in the ratio 147/160.  To convert from 44.1 to
48, for example, we (conceptually):
    1) interpolate 159 zeros between every input sample.  This
       raises that data rate to 7.056 MHz.  Since it is
       equivalent to reconstructing with delta functions, it
       also creates images of frequency f at 44.1-f, 44.1+f,
       88.2-f, 88.2+f, ...
    2) We remove these with an FIR digital filter, leaving a
       signal containing only 0-20 KHz information, but still
       sampled at a rate of 7.056 MHz.
    3) We discard 146 of every 147 output samples.  It does not hurt
       to do so since we have no content above 24 KHz.  In
       practice, of course, we never compute the values of the
       samples we will throw out.

So we need to design an FIR filter that is flat to 20 KHz, and
down at least X db at 24 KHz.  How big does X need to be?  You
might think about 100 db, since the max signal size is roughly
+-32767, and the input quantization +- 1/2, so we know the input
had a signal to broadband noise ratio of 98 db at most.  However,
the noise in the stopband (20KHz-3.5MHz) is all folded into the
passband by the decimation in step 3, so we need another 22 db
(that's 160 in db) to account for the noise folding.  Thus 120 db
rejection yields a broadband noise equal to the original quantizing
noise.  If you are a fanatic, you can shoot for 130 db to make the
original quantizing errors dominate, and a 22.05 KHz cutoff to
eliminate even ultrasonic aliasing.  You will pay for your
fanaticism with a penance of more taps, however.

I've designed 3 filters - one minimal (but better, I suspect, than
many commercial products for this purpose), one a good compromise,
and one for fanatics.

Most of this code is in double precision for testing purposes.  If
you convert to single precision or integers, watch your step!

resample.c - source of conversion program.
gencos.c   - generates cosine test cases.
full.c     - generates a 32767 height sin wave, rounded to integers,
	     for testing the FFT program.  We pick this because the
	     correct answer is known analytically.
fft.f      - reads data, does an FFT on it, and computes signal to
	     noise metrics.  Note - this program does NOT do any
	     windowing on the input data, so the results are only
	     correct if the signal to be measured repeats exactly
	     during one fft cycle (256 samples).  The test cases
	     are picked that way.
resp.f     - computes responses of digital filters.  Slow but very
	     accurate.
makefile   - compiles programs and makes test cases.  Compiles
	     the Fortan programs fft and resp with the xlf command,
	     which is for the IBM machine.  Substitute your
	     machine's fortran compile command.  "make clean"
	     removes files that can be easily recreated from the
	     source files.

coeff.9000 - A minimal set of coefficients.  Flat +- 0.012 db to
	     20KHz, down 119 db by 24KHz, 96.5 db signal to noise
	     ratio.  (For comparison, input quantization to ideal
	     16 bits is 98 db).
coeff.12500  A better set of coefficents.  Flat +- 0.009 db to
	     20KHz, down 123 db by 23KHz, 100 db signal to noise
	     ratio.
coeff.21500  A fanatic set of coefficients.  Flat to better than
	     +- 0.001 db from 0 to 20 KHz.  Down 130 db at 22.05
	     KHz, wideband S/N >108 db.

Compiled programs:

44.1to48   - conversion program for 44.1 to 48 conversion.
48to44.1   - conversion program for other direction.
gencos     - cosine test data (double precision)
full	   - full size test data (integer)
fft	   - program for looking at results

Test cases generated by make_script:

11025at48	11025 Hz signal sampled at 48 KHz.
   Convert this to 44.1, then test using fft.
12000at48	12000 Hz signal sampled at 48 KHz.
   Check the noise floor of the FFT with this.
23000at48	23000 Hz signal sampled at 48 KHz.
   Check the filter rejection.
689at48		689.0625 Hz signal sampled at 48 KHz.
   Convert this to 44.1, then test using fft.
750at44.1	11025 Hz signal sampled at 48 KHz.
   Convert this to 48, then test using fft.
750at48		750 Hz signal sampled at 48 KHz.
   Another test of the FFT.
dc		dc signal
   Sanity check
full_height	32767 height sin wave, quantized to integers
   Should (in theory) give 98 db signal to noise ratio from the fft.

You use
   resp <coefficients
to test the filter for flatness in the passband and rejection
in the stopband.

You use
   fft <full_height
to check the fft program.  Theory says
this particular signal should have a signal power of 32767^2/2,
and a noise power of 1/12.  This leads to a signal to noise
ratio of 98.09 db.  We measure something quite close; the error
is probably due to the single precision FFT.

You use the sequence
   44.1to48 coefficients <750at44.1 >tmp
   fft <tmp
to check the completed filter.  Note that 750 Hz = 48Khz/64, so the
FFT program can analyze this accurately.  Should give the signal
to noise ratios quoted above.  Other examples are similar.  The
FFT of the DC results gives unreasonably good answers, probably due
to the fft, which is done in single precision.
