Specifically, it aims to provide:
- Flexible API
- Fast filter design using actual optimization algorithms (instead of the ubiquitous Kaiser window)
- Good performance without compromising quality
- Incorporation of low-delay requirements
Linear phase FIR filters are currently designed using Lawson's algorithm with weight update envelopes (see A weighted least squares algorithm for quasi-equiripple FIR and IIR digital filter design). The filters it produces are nearly optimal in the minimax sense (It can also be modified for least squares stopbands - see this). While not strictly elegant, it has the advantage that each iteration requires the solution of a Toeplitz system of linear equations and a couple of FFTs. The linear systems are solved quickly using preconditioned conjugate gradient.
While comparably fast, filter design using this method can still take a couple of seconds at high quality settings, therefore FSRC is able to store the designs for later re-use, so it becomes a one-time effort. For this purpose, the included test program uses the %APP_DATA%\fsrc directory on Windows and ~/.libfsrc on *NIX.
Currently, FSRC implements the usual polyphase rate conversion, as well as frequency domain resampling which, assuming a conversion factor of L/M, boils down to:
- compute the DFT of an input block
- periodically extend the transform L times (equivalent to zero stuffing in the time domain)
- apply the filter (pointwise multiplication)
- divide the spectrum into M parts and add them together (equivalent of decimation in the time domain)
- compute inverse DFT
AFAIK, FSRC is also the only library which is able to perform optimal multistage decomposition of arbitrary (sans prime) conversion ratios on the fly.
As a teaser, this readme will present a tiny comparison to libsamplerate. It might not be entirely fair, since libsamplerate allows time-varying conversion factors, while FSRC does not (yet, at least). Still, libsamplerate seems to be the only library which is both high-quality and has a decent programming interface. I'll try to add a couple more into the mix later (like SOX).
For the comparison, I've tried to use settings that match libsamplerate's best quality converter. RMAA was used to compare the quality - the 44.1kHz test signal was resampled to 96kHz and back. I've finally settled on the following:
- Peak-to-peak passband ripple of 0.0001dB
- Stopband attenuation of 166dB
- Preserve 94% of bandwith below the Nyquist rate
The results produced were as follows:
Test | libsamplerate | fsrc |
Frequency response (from 40 Hz to 15 kHz), dB: | +0.00, -0.00 | +0.00, -0.00 |
Noise level, dB (A): | -194.1 | -210.8 |
Dynamic range, dB (A): | 133.2 | 133.2 |
THD, %: | 0.0000 | 0.0000 |
IMD + Noise, %: | 0.0002 | 0.0002 |
Stereo crosstalk, dB: | -194.5 | -213.2 |
To compare performance, I wrote a program which resamples a 5min long sine wave from 44.1kHz to 96kHz.
The numbers were (Core 2 Duo T5600):
- FSRC (Overlap-Save) - ~5.6s
- FSRC (Polyphase) - ~16.1s
- libsamplerate - ~103.9s
Keep in mind, the FFT resampling is not working at its peak, as mentioned at the top of the page.