Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,40 @@ env:
CARGO_TERM_COLOR: always

jobs:
build:

# Test with default features (std + rustfft)
test-rustfft:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Build
- name: Build with rustfft (default)
run: cargo build --verbose
- name: Run tests
- name: Run tests with rustfft
run: cargo test --verbose
- name: Run tests with rayon
run: cargo test --verbose --features rayon

# Test with microfft backend (no_std)
test-microfft:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build with microfft (no_std)
run: cargo build --no-default-features --features microfft-backend --verbose
- name: Run tests with microfft
run: cargo test --no-default-features --features microfft-backend --verbose
- name: Check lib compiles in no_std
run: cargo check --no-default-features --features microfft-backend --lib

# Compare both backends to ensure identical behavior
backend-comparison:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run backend comparison script
run: ./scripts/compare_backends.sh
- name: Upload comparison results
if: always()
uses: actions/upload-artifact@v4
with:
name: backend-comparison-results
path: results_*.txt
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
/target
*.png
results_microfft.txt
results_rustfft.txt
no_std_test/target
30 changes: 16 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
[package]
name = "stft-rs"
description = "Simple, streaming-friendly STFT implementation with mel spectrogram support"
version = "0.4.1"
description = "Simple, streaming-friendly, no_std compliant STFT implementation with mel spectrogram support"
version = "0.5.0"
edition = "2024"
authors = ["David Maseda Neira <david.masedan@gmail.com>"]
license = "MIT"
repository = "https://github.com/wizenink/stft-rs"

[dependencies]
ndarray = "0.17.1"
num-traits = "0.2"
rustfft = "6.4.1"
num-traits = { version = "0.2", default-features = false, features = ["libm"] }
rustfft = { version = "6.4.1", optional = true }
microfft = { version = "0.6.0", optional = true }
rayon = { version = "1.11", optional = true }

[features]
default = ["rayon"]
default = ["std"]
std = ["num-traits/std", "rustfft-backend"]
rustfft-backend = ["dep:rustfft"]
microfft-backend = ["dep:microfft"]
rayon = ["rustfft-backend", "dep:rayon"]

[dev-dependencies]
criterion = { version = "0.7.0", features = ["html_reports"] }
Expand Down
72 changes: 67 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ High-quality, streaming-friendly STFT/iSTFT implementation in Rust working with
- **Batch Processing**: Process entire audio buffers at once
- **Streaming Support**: Incremental processing for real-time applications
- **High Quality**: >138 dB SNR reconstruction
- **no_std Support**: Run on embedded systems without the standard library! 🚀
- **Dual FFT Backends**: Choose the right backend for your environment
- `rustfft` (default): Full-featured for std environments, supports f32/f64 and any FFT size
- `microfft`: Lightweight for no_std/embedded, f32 only, power-of-2 sizes up to 4096
- **Dual Reconstruction Modes**:
- **OLA** (Overlap-Add): Optimal for spectral processing
- **WOLA** (Weighted Overlap-Add): Standard implementation
Expand Down Expand Up @@ -112,7 +116,7 @@ use stft_rs::prelude::*;

This exports:

- Core types: `BatchStft`, `BatchIstft`, `StreamingStft`, `StreamingIstft`, `StftConfig`, `StftConfigBuilder`, `Spectrum`, `SpectrumFrame`
- Core types: `BatchStft`, `BatchIstft`, `StreamingStft`, `StreamingIstft`, `StftConfig`, `StftConfigBuilder`, `Spectrum`, `SpectrumFrame`, `Complex`
- Type aliases: `StftConfigF32/F64`, `StftConfigBuilderF32/F64`, `BatchStftF32/F64`, `BatchIstftF32/F64`, `StreamingStftF32/F64`, `StreamingIstftF32/F64`, `SpectrumF32/F64`, `SpectrumFrameF32/F64`
- Mel types: `MelConfig`, `MelSpectrum`, `BatchMelSpectrogram`, `StreamingMelSpectrogram`, `MelScale`, `MelNorm` (+ F32/F64 aliases)
- Enums: `ReconstructionMode`, `WindowType`, `PadMode`
Expand Down Expand Up @@ -404,10 +408,58 @@ let channels = deinterleave(&interleaved, 2);
let interleaved = interleave(&channels);
```

Disable parallel processing: `cargo build --no-default-features`

See `examples/multichannel_stereo.rs` and `examples/multichannel_midside.rs` for more.

## Embedded / no_std Support

stft-rs can run on embedded systems without the standard library! Perfect for audio processing on microcontrollers, DSPs, and bare-metal environments.

### Using the microfft Backend for no_std

```toml
[dependencies]
stft-rs = { version = "0.4", default-features = false, features = ["microfft-backend"] }
```

**Important notes:**

- microfft backend only supports f32 (not f64)
- FFT sizes must be power-of-2 from 2 to 4096
- Requires an allocator (uses `alloc` crate)

### Example no_std Configuration

```rust
#![no_std]

extern crate alloc;
use alloc::vec::Vec;
use stft_rs::prelude::*;

// Works great on embedded!
let config = StftConfigF32::builder()
.fft_size(2048) // Must be power-of-2
.hop_size(512)
.build()
.expect("Valid config");

let stft = BatchStftF32::new(config.clone());
let istft = BatchIstftF32::new(config);

let signal: Vec<f32> = Vec::from_slice(&audio_buffer);
let spectrum = stft.process(&signal);
let reconstructed = istft.process(&spectrum);
```

### Feature Flags

- `std` (default): Standard library support with rustfft backend
- `rustfft-backend`: Use rustfft for FFT (supports f32/f64, any size)
- `microfft-backend`: Use microfft for no_std (f32 only, power-of-2 sizes)
- `rayon`: Enable parallel multi-channel processing (requires std)

**Note:** You cannot enable both `rustfft-backend` and `microfft-backend` at the same time.

## Performance Characteristics

- **Batch Mode**: Optimized for throughput, minimal allocations
Expand Down Expand Up @@ -517,8 +569,18 @@ Tests verify:

## Dependencies

- `rustfft`: High-performance FFT implementation
- `ndarray`: Only for internal padding operations (minimal usage)
Core dependencies:

- `num-traits`: Generic numeric traits (no_std compatible with `libm`)

FFT backends (mutually exclusive):

- `rustfft` (default): High-performance FFT for std environments
- `microfft` (optional): Lightweight FFT for no_std/embedded

Optional dependencies:

- `rayon`: Parallel multi-channel processing (requires std)

## License

Expand Down
Loading