audio-resample-bsd 0.2.1

RT-safe audio resampling crate (rubato-based) — the only processing interface callable directly from the real-time audio thread
Documentation

audio-resample-bsd

License: BSD-2-Clause Crates.io

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
cargo test         # 36 tests (22 unit + 3 integration + 3 property + 4 SNR + 4 RT-alloc)
cargo bench        # criterion — RT-path throughput / latency regression watch
cargo run --example resample_441_to_48k

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.