audio-resample-bsd
RT-safe audio resampling (rubato-based) — defines the only processing interface that may be called directly from the real-time (RT) audio thread.
Note: The doc comments on each public item are the primary reference. This README is an overview only.
Role
A sample-rate conversion layer for real-time audio graphs. Codecs, DSP
primitives, and graph nodes all perform sample-rate conversion
(44.1k <-> 48k <-> 96k) through the [Resampler] trait defined here. The
rubato 4.0-backed implementation RubatoResampler satisfies that contract.
Dependencies
| Dependency | Version | Purpose |
|---|---|---|
audio-core-bsd |
0.1.0 (path dep) | shared types (AudioFrame, AudioError) — planar layout compatibility |
rubato |
4 (Fft synchronous, FixedSync::Input) |
RT-safe process_into_buffer — zero-copy via SequentialSlice |
thiserror |
2.0 | ResampleError derive |
rubato 4.0 documents an allocation-free processing path and is the only DSP crate in this stack with an explicit RT-safety statement.
Data layout — planar flat
Input and output are flat &[f32] buffers in planar layout:
[ch0_frames..., ch1_frames...]. This matches audio_core_bsd::AudioFrame::samples
exactly, so an AudioFrame can be passed directly with no extra copy or
rearrangement. The channel count is fixed when the implementation is constructed.
Real-time safety boundary
Only [Resampler::process_into_buffer] may be called from the RT thread. On
this path, heap allocation / locking / panicking / system calls are all
forbidden (same principle as the audio-core-bsd AudioNode RT contract).
Every buffer is pre-allocated at construction.
[Resampler::set_rate] is not RT-safe — it rebuilds the inner resampler
(allocating), so it must be called from a configuration/worker thread, only
between audio cycles. The RT-alloc=0 guarantee applies only to the
process_into_buffer path.
Verification
| Gate | Criterion | Measured |
|---|---|---|
| Audio Quality (SNR) | round-trip 44.1k <-> 48k <-> 96k SNR >= 90 dB | round-trip 125-131 dB (tests/resample_snr.rs) |
| RT-safety (alloc) | process_into_buffer allocation == 0 |
alloc = 0 (tests/rt_alloc_free.rs, CountingAllocator) |
| Property | broad configs: no panic, finite output, bounded delay | 3 proptests pass (tests/resample_property.rs) |
| Integration | AudioFrame (planar) passed directly, zero-copy |
3 integration tests pass (tests/audio_frame_integration.rs) |
| FreeBSD target | cargo check --target x86_64-unknown-freebsd |
0 errors (all-targets); native FreeBSD CI via .github/workflows/freebsd-matrix.yml |
Status
0.x — experimental. The public API (Resampler / ResampleError /
RubatoResampler) is not yet frozen. Breaking changes are expected before a
1.0 release.
- edition: 2021
- MSRV: 1.85
- license: BSD-2-Clause
License
BSD-2-Clause. See LICENSE.