ARDFTSRC
A rust implementation of the Arbitrary Rate Discrete Fourier Transform Sample Rate Converter (ARDFTSRC) algorithm.
ardftsrc is a streaming audio sample-rate converter, and is appropriate for both realtime and offline resampling.
Generally ardftsrc is preferred over other resamplers when quality is paramount. Although it is generic over both f32 and f64, it is highly recommended to use it with f64, even when processing an f32 audio stream.
It is among the top scoring resampling libraries on HydrogenAudio Sample Rate Conversion Comparison, topping out with a balanced score of 99.73%. It is more compute intensive than other resamplers, so consider sinc rubato if you want more efficiency. See PERFORMANCE.md for a detailed speed and quality comparison vs rubato.
Quick Start
Use InterleavedResampler::process_all to resample a complete interleaved audio stream for a single track.
use ;
Chunk Resampling
Use chunk resampling when you can control both read and write buffer sizes. Query input_buffer_size() and output_buffer_size() and size your input and output slices to the sizes required. The chunk API is more efficient than the streaming API and is preferred when you are not doing live resampling.
There are two chunked resamplers depending on the shape of your audio:
InterleavedResampler- for interleaved audioPlanarResampler- for planar audio.
Internally ardftsrc uses planar representation, so PlanarResampler is more efficient, but if you're already working with interleaved audio, prefer InterleavedResampler since it has an optimized de-interleave / re-interleave path. Working with all chunked resamplers is the same:
- Create the resampler with
let resampler = Resampler::new(config) - Query the required input buffer size and output buffer size with
resampler.input_buffer_size()andresampler.output_buffer_size() - Call
process_chunk(...)for each chunk, using the appropriate buffer sizes. - Call
process_chunk_final(...)for the final chunk, it can be undersized. - Finally, call
finalize(...)once per stream to emit delayed tail samples and reset stream state.
use ;
Gapless Context
For adjacent tracks, you can set edge context before processing:
pre(Vec<T>): tail frames from the previous trackpost(Vec<T>): head frames from the next track
post(...) may be called any time while the current stream is still active, but it must be
set before process_chunk_final(...).
This enables live gapless handoff: while track A is streaming, once track B is known you can
call post(...) on A with B's head samples so A's stop-edge uses real next-track context.
Realtime Resampling
ardftsrc-rs provides both rodio integration via RodioResampler (rodio feature) and the ability to build your own custom realtime audio resampling pipeline via RealtimeResampler.
Rodio integration
Enable the rodio feature to use RodioResampler to wrap a rodio::Source and resample it in realtime in your rodio pipeline.
When playing from a buffered audio source such as a file or a buffered stream, it is recommended to use config.with_rodio_fast_start(true), which will
avoid initial output delay by pulling samples from the upstream source to prime the resampler. For very-realtime sources such as microphones or similar,
do not enable fast-start.
More examples can be found:
- Basic rodio example:
examples/rodio_adapter.rs - Span-switching rodio example:
examples/rodio_adapter_with_spans.rs
Batching
Use batching when you have multiple full tracks to convert with the same configuration.
InterleavedResampler::batch(...): processes each interleaved input as an independent stream (no context shared between tracks).InterleavedResampler::batch_gapless(...): preserves adjacent-track context for gapless album-style playback.PlanarResamplerexposes the samebatch(...)andbatch_gapless(...)APIs for already-planar inputs.
Enable the rayon feature to parallelize work across tracks.
use ;
Quality Tuning and Presets
ARDFTSRC is built for quality over speed, and despite supporting both f32 and f64 should almost always be run as f64. To resample f32 audio, it is recommended to convert f32 samples to f64, resample them using InterleavedResampler<f64> or PlanarResampler<f64>, then convert back to f32.
If you want better performance than what this project offers, consider using a sinc resampler such as rubato.
Presets are pre-vetted Config for various quality levels.
let config = PRESET_GOOD
.with_input_rate
.with_output_rate
.with_channels;
| Preset | Quality | Bandwidth | Recommended use | Quality metrics |
|---|---|---|---|---|
PRESET_FAST |
512 |
0.832 |
Fast preset for realtime workloads. | f32, f64 |
PRESET_GOOD † |
1878 |
0.911 |
Balanced preset for realtime quality. | f64 |
PRESET_HIGH |
73622 |
0.987 |
High quality for offline use. | f64 |
PRESET_EXTREME |
524514 |
0.995 |
Maximum quality, intended for offline use. | f64 |
† You should probably use PRESET_GOOD. It's fast, has very high quality metrics, and has lower pre-ringing artefact as compared PRESET_HIGH and PRESET_EXTREME.
Feature Flags
| Flag | Enables | Default |
|---|---|---|
rodio |
rodio integration via rodio::RodioResampler |
No |
rayon |
Parallelized resampling (batch() and process_all() APIs) |
No |
avx |
FFT AVX SIMD | Yes |
sse |
FFT SSE SIMD | Yes |
neon |
FFT NEON SIMD for ARM / Mac | Yes |
wasm_simd |
FFT WebAssembly SIMD | Yes |
audioadapter |
Experimental audioadapter support |
No |
Runtime feature detection is in place for all SIMD except webassembly.