Skip to content

Repository files navigation

embedded-dsp

embedded-dsp

crates.io docs.rs CI codecov License: MIT OR Apache-2.0

A high-performance #![no_std] Rust Digital Signal Processing library designed for microcontrollers (Cortex-M, RISC-V, AVR, Xtensa), bare-metal DSP, and real-time audio/sensor pipelines.

Upgrading from 0.5? See MIGRATING.md for the 0.6 breaking changes (removed width-suffixed aliases/wrappers and the duplicate filtering::Dsm/XorShift32).


Highlights

  • #![no_std] First: Pure core compatibility with zero heap allocations.
  • Fixed & Float Parity: CMSIS-style f32, f64, and q7/q15/q31 — interoperable with the fixed crate (optional fixed feature, enabled by default) with zero-dependency fallback newtypes — plus the polymorphic DspSample trait. Filters, PID, Hilbert transform, CFFT/BFP and complex-math are implemented once as generic DspSample code and verified bit-exact against the per-width kernels they replace, and the 0.5-era width-suffixed aliases and wrappers were removed in 0.6 (see MIGRATING.md).
  • Hardware Acceleration: ARM Cortex-M assembly intrinsics (smlad, smlald, ssat, qadd16) via cortex-m-dsp, with portable SWAR vector fallbacks.
  • Pure-Integer CORDIC Engine: Shift-and-add sin, cos, atan2, polar conversion, and sqrt requiring no hardware multipliers.
  • Streaming Pipelines: Zero-allocation DspNode composable processing chains (Chain, Gain, Limiter).
  • Production Tested: CI runs the full test suite on the host and cargo check --all-targets --all-features plus a no_std build on six embedded/WebAssembly targets (thumbv6m-none-eabi, thumbv7em-none-eabi, thumbv7em-none-eabihf, thumbv8m.main-none-eabihf, riscv32imc-unknown-none-elf, wasm32-unknown-unknown), and enforces a 96% line-coverage floor on the library.

⚡ embedded-dsp Studio (Interactive DSP Workbench)

🌐 Launch Live WebAssembly Studio — Run real-time filter design, spectral forensics, and micro-benchmarks directly in your browser.

An interactive desktop & browser testbench inspired by DSP-Testbench and embedded-nn:

# Run native desktop GUI
cargo run -p embedded-dsp-studio
  • Dual Signal Lab: Anti-aliased PolyBLEP oscillators (Saw/Square/Triangle/Sine), chirp sweeps (linear/exponential), pink noise ($1/f$), white noise, and Dirac impulse.
  • Filter & Pipeline Rack: Real-time sweepable Biquad IIR filters, Andrew Simper 2x oversampled State Variable Filters (SVF), Audio EQ Cookbook shelves, and Q15 quantization floor.
  • Forensics & Analyzer: 4096-point FFT magnitude, Welch PSD, oscilloscope, Lissajous phase goniometer, and true RMS/peak meters.
  • Impulse Response Analyzer: 4096-sample freeze buffer with settling time, peak gain, and energy measurements.
  • WAV & CSV Export/Import: Export forensic snapshots and waveforms directly to 16-bit PCM .wav or .csv files.
  • Zero-Allocation MCU Codegen: Generates instant C (CMSIS-DSP) and #![no_std] Rust code snippets tuned in the GUI.

Comparison with idsp

idsp (0.22, by Robert Jördens / QUARTIQ) is the other established #![no_std], integer-first DSP crate, used in production by Stabilizer. embedded-dsp ports and re-verifies idsp's fixed-point/integer algorithms — a superset where they overlap — and adds transforms, audio/vision, sensor fusion, control, and tooling on top. The table below is checked against idsp 0.22.1; honest gaps are marked and explained after the table.

Feature embedded-dsp idsp
#![no_std], zero-allocation
Fixed point q7/q15/q31 + fixed interop ✅ (i8/i16/i32/i64)
cossin LUT (i32) ✅ ~5e-6 RMS ✅ ~4e-6 RMS
atan2 (i32) ✅ ~1.3e-6 rad ✅ ~1.3e-6 rad
Integer PLL / reciprocal RPLL
Integer lowpass (IntLowpass<N>), unwrap, saturating_scale_i32
CORDIC modes ✅ circular + hyperbolic (vectoring), no band or panicking input ➖ circular and linear div are correct; mul/cosh_sinh limited to a ±0.5 band by a bug (see note)
Biquad f32/f64 DF1 + DF2T
Biquad i32 clamping / anti-windup / guard bits
Biquad fixed-point noise shaping
Biquad generic integer i8/i16/i32/i64 BiquadInt<T>
Biquad DF1 wide (Q32.32) / dither actions
Control-plane settings via miniconf config::BiquadSettings
Audio EQ builder / WebAudio export EqFilter/EqShape/BiquadType validating builder, every RBJ type incl. IHo, plus WebAudioFilter iir::coefficients::{Filter, Shape, Type, WebAudio}
Normal-form IIR ✅ arbitrary numerator ⚠️ forced p.im·z⁻¹ factor
Wave digital allpass filters
PI²D² controller builder (per-action limits) PidBuilder
Half-band Type I–IV linear-phase FIR
Half-band cascades with known-good taps ✅ rates 2/4/8/16/32, 140 dB + 98 dB ✅ rates 2/4/8/16/32, 140 dB
CIC decimator/interpolator
General FIR, LMS/NLMS
FFT (CFFT/RFFT/BFP Q15/Q31), DCT, DWT, Hartley, Hilbert
Goertzel, Mel/MFCC, VAD, compressor/gate
Welch/Burg PSD analysis
Kalman ✅ const-generic, EKF, square-root, and composable models (Estimate/Dynamics/Transition/Observation, vector + optional measurements, control input) ➖ composable Transition/Observation only, with scalar measurements and linear models
2D vision, beamforming, GCC-PHAT, quaternions, matrices
Lock-in amplifier
Dither + MASH delta-sigma
Resampling (polyphase, fractional, half-band)
Swept-sine stimulus Sweep + AccuOsc + Farina inverse_filter Sweep::inverse_filter
Block/lane block processing DspNode, Split/SplitProcess, Lanes, Pair, Parallel, ByLane, typed View/ViewMut (FrameMajor/LaneMajor, as_layout), chunk bridges (ChunkInOut, PerFrame, FnSplitProcess), gated Buffer ✅ same ideas in dsp-process; the scratch-buffer Major is deliberately not mirrored (see note)
Companding (G.711 µ/A-law)
In-repo micro-benchmarks ✅ (tests/embedded)
Python bindings embedded-dsp-py (PyO3, abi3) ✅ (py / numpy)
Interactive WebAssembly studio

Legend: ✅ full support · ➖ partial/alternative coverage · ⚠️ quirk · ❌ not provided.

Where idsp still leads: nowhere in API surface. The one deliberate omission is Major (block/lane scratch-buffer traversal), argued below; the Python lead is closed by embedded-dsp-py, a PyO3 stable-ABI module exposing the audio-EQ designer, FIR, and biquad cascades.

CORDIC modes. idsp's linear mul and hyperbolic cosh_sinh are correct only inside a ±0.5/ ±0.3 band (an upstream sign bug); div and the circular/hyperbolic modes this crate ports are fine and bit-matched, pinned by tests/idsp_cordic_probe.rs. embedded-dsp implements hyperbolic vectoring instead of rotation: both outputs are representable across their full domain, measure to ~6e-9, and have no band or panicking input — reaching |z| ≈ 0.63 at Q1.31 full scale, about twice what idsp's rotation mode manages.

Major (stage-by-stage block traversal). Not ported: Chain<A, B> is homogeneous over one sample type, so the intermediate-type problem Major solves doesn't arise here — it's just &mut [T]. Only Buffer/ChunkInOut have real block specializations; every other stage is per-sample, where sample-major is already optimal. The manual one-liner (a.block(&x, &mut scratch); b.block(&scratch, &mut y)) already gets the same effect; a caller-owned-scratch helper is worth adding only once a block-capable stage — most likely the FIRs — needs it.


Module Overview

Category Key Algorithms & Structs
Filtering & Design FIR, Biquad IIR (DF-I & Transposed DF-II), LMS/NLMS, Butterworth/Chebyshev/elliptic design, Kaiser-windowed sinc FIR, RRC/RC/GMSK-TX pulses, Windowed-Sinc, $L_\infty/L_2$ SOS Quantization & SQNR analysis, DC Blocker.
Spectral & Transforms CFFT, RFFT (packed), Block Floating-Point FFT (cfft_bfp_q15/q31), Hilbert Transform FIR & Analytic Signal (generic HilbertTransform<T>), Real Cepstrum, DCT-IV, FWHT, Haar, Hartley, Daubechies-4 DWT, Welch & Burg AR PSD.
Audio & Voice Goertzel tone detector, Mel & Generalized filterbanks, MFCC, Q15 VAD, Dynamics Compressor with soft knee, Noise Gate, streaming AGC.
Control & Power FOC current/speed PID, Clarke & Park transforms, SOGI-PLL (grid synchronization/resolvers), Costas Loop carrier recovery.
Analog modem FM phase-accum mod/demod, DSB-AM envelope, SSB USB/LSB (reuses Hilbert transformer).
Sensor Fusion & Spatial Square-Root Kalman Filter (SquareRootKalmanFilter), EKF, composable Kalman models (kalman_compose: Estimate, Dynamics, Transition, Observation, VectorObservation, Direct, Optional), 2D Spatial/Vision (Sobel, Median, DCT-II), Delay-and-Sum Beamformer, GCC-PHAT TDoA locator.
Multi-rate & Resampling CIC Decimator/Interpolator with bit-growth normalization, Polyphase Decimation & Interpolation (Float & Q15), fractional linear resampler, arbitrary-rate polyphase resampler, Gardner symbol sync.
FEC CRC-8/16/24/32, 8-bit checksum, Hamming(7,4) nibble/byte codecs.
Sequences Maximal-length LFSR (MSequence) for PN sequences and additive scramble.
Signal Generation PolyBLEP anti-aliased oscillator (PolyBlepOscillator: saw/square/triangle/sine), white & Kellett pink noise, linear/exponential ChirpSweep, exponential swept-sine Sweep with delta-sigma fractional phase (AccuOsc, Accu<T>) and its Farina inverse filter (Sweep::inverse_filter) for impulse-response measurement.
Math, CORDIC & Numerics BFloat16 (50% SRAM buffer reduction), FloatFloat (~48-bit double-single extended precision on f32 FPU), Fast Bit-Manip Log/Pow/dB (fast_log2_f32, fast_pow2_f32, fast_gain_to_db_f32), EFT (two_sum_f32/two_sum_f64, two_prod_f32/two_prod_f64, two_diff_f32, two_div_f32), Horner polynomials & roots, strided dot products, CORDIC engine (circular sin/cos, polar, atan2, sqrt + hyperbolic sqrt_atanh2, atanh), Complex math, Quaternions (nalgebra interop), 8 window types (Hanning, Hamming, Blackman, Blackman-Harris, Bartlett, Welch, flat-top, Kaiser) with apply_window_f32/apply_window_q15, G.711 $\mu$/A-law companding.

Quick Start

Add to your Cargo.toml:

[dependencies]
# Standard std environment (all modules enabled)
embedded-dsp = "0.6.0"

# Bare-metal #![no_std] with libm
embedded-dsp = { version = "0.6.0", default-features = false, features = ["libm", "full"] }

# Minimal firmware footprint (only FIR/Biquad filtering + basic math)
embedded-dsp = { version = "0.6.0", default-features = false, features = ["libm", "filtering", "basic-math"] }

Basic Example

use embedded_dsp::*;

fn main() {
    // 1. Fixed-Point Saturating Addition
    let a = [q15::from_bits(20000), q15::from_bits(25000)];
    let b = [q15::from_bits(15000), q15::from_bits(10000)];
    let mut out = [q15::ZERO; 2];
    add_q15(&a, &b, &mut out); // [I1F15::MAX, I1F15::MAX] (saturated)

    // 2. Biquad Filter Cascade
    let coeffs = biquad_lowpass_coeffs(1000.0, 48000.0, core::f32::consts::FRAC_1_SQRT_2);
    let mut filter = BiquadCascade::<5, 4>::new(coeffs);
    let input = [1.0f32, 0.5, -0.2, 0.1];
    let mut filtered = [0.0f32; 4];
    filter.process(&input, &mut filtered);

    // 3. Robust Square-Root Kalman Sensor Filter
    let mut kf = KalmanFilter1D::new(0.0, 1.0, 0.01, 0.1);
    kf.predict(0.0);
    let _est = kf.update(10.2);

    // 4. In-Place FFT
    let mut fft_buf = [0.0f32; 128]; // 64 complex pairs [re, im, ...]
    cfft_f32(&mut fft_buf, 64, 0, 1);
}

Cookbook & Examples

Need copy-paste code for real-world projects? Check the embedded-dsp Cookbook:

  • Motor Control: Sensorless Field-Oriented Control (FOC) with Clarke/Park and Space-Vector PWM.
  • Real-Time Audio DMA: DC-Blocker + Biquad Peaking EQ + Peak Limiter streaming pipeline.
  • Machine Health: Vibration spectrum analysis and bearing fault detection using Burg AR PSD.
  • Multi-rate ADC: High-speed Cascaded Integrator-Comb (CIC) decimation.
  • Acoustic Edge AI: Voice Activity Detection (VAD) & MFCC feature extraction.
  • Streaming Pipeline: Composing modular DspNode signal processing chains.

Run any included example directly with cargo:

cargo run --example basic_usage
cargo run --example motor_control_foc
cargo run --example audio_speech_pipeline
cargo run --example sensor_fusion_navigation
cargo run --example filter_workbench_and_analysis
cargo run --example spectral_radar_transforms
cargo run --example spatial_vision_processing
cargo run --release --example perf_comparison

Benchmarks

Native micro-benchmarks (run in CI, results attached to the job summary):

cargo bench -p embedded-dsp --bench dsp_benchmarks

Bare-metal cycle counts on Cortex-M are in tests/embedded and include the integer primitives shared with idsp (cossin, atan2, IntPll).


License

Dual-licensed under either MIT or Apache-2.0 at your option. See LICENSE-MIT and LICENSE-APACHE.

About

A #![no_std] digital signal processing library for microcontrollers, embedded systems, and real-time audio/sensor math

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages