audio_samples 2.0.1

A typed audio processing library for Rust that treats audio as a first-class, invariant-preserving object rather than an unstructured numeric buffer.
Documentation

AudioSamples

Typed, invariant-preserving audio processing for Rust

Crates.io Docs.rs License: MIT


Overview

Most audio libraries hand you a bare buffer. In Python it is a NumPy array whose dtype is explicit but whose meaning is not: the sample rate, amplitude range, channel layout, and interleaving live elsewhere, if they are tracked at all. Rust libraries give you fast, safe primitives but still leave you holding the raw buffer, writing your own conversions, and carrying those conventions in your head. Mismatches between them, such as a stale sample rate after resampling or a buffer that was interleaved when the next stage expected planar, are a recurring source of bugs.

audio_samples puts that metadata in the type. [AudioSamples<T>] pairs the PCM data with its sample rate, channel count, and memory layout, and every operation either preserves those invariants or updates them explicitly. The sample type T (u8, i16, [I24], i32, f32, f64) is part of the type, so format and bit-depth conversions are checked and scaled correctly rather than left to ad hoc casts.


Installation

cargo add audio_samples

The default feature set (bare-bones) is the core types and traits with no optional dependencies. Add features for the operations you need; see Features.

Upgrading from 1.x? See the migration guide.


Quick Start

Creating audio

Build AudioSamples from an ndarray, or generate a signal. Construction is fallible because the data, channel count, and sample rate must agree.

use audio_samples::{AudioSamples, sample_rate, sine_wave};
use ndarray::array;
use std::time::Duration;

fn main() -> audio_samples::AudioSampleResult<()> {
    // Mono, from a slice of samples.
    let _mono = AudioSamples::new_mono(array![0.1f32, 0.5, -0.3, 0.8], sample_rate!(44_100))?;

    // Stereo, from a 2-D (channels x samples) array.
    let _stereo = AudioSamples::<f32>::new_multi_channel(
        array![[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]],
        sample_rate!(44_100),
    )?;

    // Or generate one: a 440 Hz sine, 1 second, amplitude 0.5.
    let _tone = sine_wave::<f32>(440.0, Duration::from_secs(1), sample_rate!(44_100), 0.5);
    Ok(())
}

Generators cover the classic oscillators plus logarithmic chirps (exponential_chirp), band-limited square/sawtooth/triangle waves, FM (fm_signal), and white/pink/brown noise.

A processing pipeline

Operations carry the sample rate and channel layout with the data and chain through the borrowing API. Here two tones are mixed, the low one is filtered out, the result is peak-normalized, and its level is read back. Enable the processing feature.

use audio_samples::{AudioProcessing, AudioStatistics, NormalizationConfig, sample_rate, sine_wave};
use std::time::Duration;

fn main() -> audio_samples::AudioSampleResult<()> {
    let sr = sample_rate!(44_100);
    let dur = Duration::from_secs(1);

    // 100 Hz and 5 kHz, mixed.
    let signal = sine_wave::<f32>(100.0, dur, sr, 0.5) + sine_wave::<f32>(5_000.0, dur, sr, 0.5);

    // High-pass above 1 kHz, then peak-normalize. Each step returns a new value.
    let cleaned = signal
        .high_pass_filter(1_000.0)?
        .normalize(NormalizationConfig::peak(1.0))?;

    println!(
        "{} channel(s) at {} Hz, peak {:.3}, rms {:.3}",
        cleaned.num_channels().get(),
        cleaned.sample_rate().get(),
        cleaned.peak(),
        cleaned.rms(),
    );

    // The `*_in_place` variants mutate instead of returning a new value.
    let mut buf = cleaned;
    buf.scale_in_place(0.5);
    Ok(())
}

Type conversions

Conversions are audio-aware: integer PCM is scaled to and from the float [-1.0, 1.0] range rather than cast blindly.

use audio_samples::{AudioTypeConversion, sample_rate, sine_wave};
use std::time::Duration;

let pcm = sine_wave::<i16>(440.0, Duration::from_secs(1), sample_rate!(44_100), 0.8); // i16 PCM
let as_float = pcm.as_f32();   // scaled into [-1.0, 1.0]
let _back = as_float.as_i16(); // and back to i16

Spectral analysis

Enable the transforms feature for FFT/STFT and the spectral feature suite.

use audio_samples::{AudioStatistics, AudioTransforms, ChannelReduction, nzu, sample_rate, sine_wave};
use spectrograms::{StftParams, WindowType};
use std::time::Duration;

fn main() -> audio_samples::AudioSampleResult<()> {
    let audio = sine_wave::<f32>(440.0, Duration::from_millis(200), sample_rate!(44_100), 0.8);

    // Short-time Fourier transform.
    let params = StftParams::new(nzu!(1024), nzu!(256), WindowType::Hanning, true)?;
    let _stft = audio.stft(&params)?;

    // A derived spectral feature (brightness), in Hz.
    let centroid = audio.spectral_centroid(ChannelReduction::Average)?;
    println!("spectral centroid: {centroid:.0} Hz");
    Ok(())
}

The full transform set (FFT, MFCC, chromagram, CQT, PSD, inverse STFT) and the rest of the spectral features are listed under Features.


Features

The default feature is bare-bones: the core types and traits, no optional dependencies. Enable the rest as needed.

Core operations

Feature Description
statistics Peak, RMS, mean, variance, zero-crossings; the spectral feature suite (centroid, rolloff, bandwidth, flatness, contrast, slope, crest) when transforms is also enabled
processing Normalization, scaling, clipping, DC-offset removal (requires statistics)
editing Trim, pad, reverse, fade, concatenate, perturb (requires statistics, random-generation)
channels Interleave/deinterleave, mono/stereo conversion, channel extraction
iir-filtering Butterworth, Chebyshev I and II, Elliptic (Cauer), and Bessel filters; low-, high-, band-pass and band-stop responses; zero-phase filtfilt; design-once streaming SosFilter
parametric-eq Parametric EQ bands and ThreeBandEqConfig (requires iir-filtering)
dynamic-range Compression, limiting, gating, expansion via config structs, with side-chain support
envelopes Amplitude, RMS, and attack-decay envelope followers
vad Voice activity detection

Spectral and analysis

Feature Description
transforms FFT, STFT and inverse STFT, MFCC, chromagram, CQT, power spectral density
psychoacoustic Bark/Mel band layouts, absolute threshold of hearing, masking thresholds, SMR (requires transforms)
pitch-analysis YIN and autocorrelation pitch detection and tracking (requires transforms)
onset-detection Onset detection (requires transforms, peak-picking, processing)
beat-tracking Beat tracking and tempo estimation (estimate_tempo)
peak-picking Peak picking on onset-strength envelopes
decomposition Harmonic/percussive source separation (requires onset-detection)

Utility

Feature Description
resampling Sample-rate conversion via rubato
random-generation White, pink, and brown noise generators
fixed-size-audio Stack-allocated fixed-size buffers
plotting Interactive HTML plots (waveform, spectrum, phase, spectrogram, Lissajous) via plotly
static-plots PNG/SVG export (requires plotting; see PLOTTING.md)
simd SIMD-accelerated sample conversions via the wide crate (stable; results are bit-identical to the scalar path)

Bundles

Feature Description
full Everything below
full_no_plotting Everything except plotting

Documentation

Full API documentation: https://docs.rs/audio_samples. Architecture notes are in documentation/ARCHITECTURE.md.


Examples

The repository includes runnable examples in examples/, each annotated with its required feature flags. Run one with, for example:

cargo run --example transforms --features transforms,statistics

A larger demo lives in a separate repository:


Companion Crates


License

MIT.


Citing

If you use AudioSamples in research, please cite:

@inproceedings{geraghty2026audio,
  author    = {Geraghty, Jack and Golpayegani, Fatemeh and Hines, Andrew},
  title     = {Audio Made Simple: A Modern Framework for Audio Processing},
  booktitle = {ACM Multimedia Systems Conference 2026 (MMSys '26)},
  year      = {2026},
  month     = apr,
  publisher = {ACM},
  address   = {Hong Kong, Hong Kong},
  doi       = {10.1145/3793853.3799811},
  note      = {Accepted for publication}
}

Contributing

Contributions are welcome. Please open an issue or pull request, and see CONTRIBUTING.md for guidance.