| Crates.io | desperado |
| lib.rs | desperado |
| version | 0.2.0 |
| created_at | 2025-11-10 09:56:12.18108+00 |
| updated_at | 2026-01-19 16:32:49.259048+00 |
| description | Iterate and stream I/Q samples from stdin, files, TCP streams and SDR devices |
| homepage | |
| repository | https://github.com/xoolive/desperado |
| max_upload_size | |
| id | 1925017 |
| size | 1,064,315 |
A unified Rust library for reading I/Q samples from files, SDR devices, and streams
Desperado is a library designed to factorize and reuse code for reading I/Q samples from files, SDR devices, and other sources.
Desperado provides a unified interface for iterating (synchronously) and streaming (asynchronously) complex I/Q samples in Complex<f32> format.
The library intentionally does not include demodulation, focusing instead on providing a consistent interface over various sources.
The name "Desperado" is a playful nod to DSP (Digital Signal Processing), and tips its hat to https://www.youtube.com/watch?v=-q93wc3-deU.
I/Q (In-phase/Quadrature) samples are the fundamental representation of radio signals in software-defined radio (SDR). They represent complex numbers where:
Together, I and Q samples capture both the amplitude and phase information of a radio signal, allowing software to process, demodulate, and analyze RF signals that have been digitized by SDR hardware.
Desperado abstracts away the complexity of reading these samples from various sources (files, devices, network streams), providing a consistent interface regardless of the source or format (8-bit, 16-bit, float, etc.).
Add Desperado to your Cargo.toml:
[dependencies]
desperado = "0.1"
To use hardware SDR devices, enable the appropriate feature flags:
[dependencies]
desperado = { version = "0.1", features = ["rtlsdr"] } # For RTL-SDR devices
# or
desperado = { version = "0.1", features = ["soapy"] } # For SoapySDR-compatible devices
# or
desperado = { version = "0.1", features = ["pluto"] } # For Adalm-Pluto devices
rtlsdr: RTL-SDR device support (DVB-T dongles)soapy: SoapySDR device support (HackRF, LimeSDR, etc.)pluto: Adalm-Pluto SDR supportThe following features are only needed for examples:
clap: Command-line argument parsing for exampleswaterfall: Waterfall plot visualization exampleaudio: FM demodulation examples with audio outputIf you're using Desperado in your project, feel free to open a PR to add it here!
use desperado::{IqFormat, IqSource};
fn main() -> desperado::Result<()> {
// Create an IQ source from a binary file
let path = "sample.iq";
let sample_rate = 96_000;
let center_freq = 162_000_000;
let chunk_size = 8136;
let iq_format = IqFormat::Cu8;
for samples in IqSource::from_file(path, center_freq, sample_rate, chunk_size, iq_format)? {
for s in samples? { // samples is a Result<Vec<Complex<f32>>, _>
println!(" I: {}, Q: {}", s.re, s.im);
}
}
Ok(())
}
Access to RTL-SDR devices is provided with the rtlsdr feature enabled.
use desperado::IqAsyncSource;
use futures::StreamExt;
#[tokio::main]
async fn main() -> desperado::Result<()> {
let device_index = 0;
let sample_rate = 2_400_000;
let center_freq = 1_090_000_000;
let gain = Some(496);
let reader = IqAsyncSource::from_rtlsdr(device_index, center_freq, sample_rate, gain).await?;
while let Some(samples) = reader.next().await {
// Process samples...
}
Ok(())
}
Desperado supports various data sources: the following table summarizes the available sources.
Methods are available in both synchronous (IqSource) and asynchronous (AsyncIqSource) versions.
| Frontend | Method name | Optional feature | Identifier |
|---|---|---|---|
| I/Q File | [Async]IqSource::from_file |
file name | |
| Standard Input | [Async]IqSource::from_stdin |
||
| TCP socket | [Async]IqSource::from_tcp |
address and port | |
| RTL-SDR | [Async]IqSource::from_rtlsdr |
rtlsdr |
device index |
| Soapy | [Async]IqSource::from_soapy |
soapy |
device arguments |
| Adalm-Pluto | [Async]IqSource::from_pluto |
pluto |
URI |
All samples are returned as Complex<f32> values, regardless of the source.
rtlsdr feature enables support for RTL-SDR devices (DVB-T dongles). It is based on the rtl-sdr-rs crate which is a pure Rust implementaiton of the RTL-SDR driver.soapy feature enables support for SoapySDR-compatible devices (HackRF, LimeSDR, BladeRF, etc.). It is based on the soapysdr crate which provides Rust bindings to the SoapySDR C++ library. The SoapySDR library must be installed separately.pluto feature enables support for Adalm-Pluto devices. It is based on the pluto-sdr crate which provides Rust bindings to the libiio C library. The libiio library must be installed separately.Contributions to include more SDR frontends (LimeSDR, HackRF, etc.) or to port existing ones to pure Rust implementations are welcome.
Desperado provides both synchronous (IqSource) and asynchronous (AsyncIqSource) interfaces. Here's how to choose:
Use Synchronous (IqSource) when:
Use Asynchronous (AsyncIqSource) when:
Performance note: For single-threaded file processing, synchronous can be faster due to less overhead. For real-time SDR applications, async is typically better.
The chunk_size parameter determines how many I/Q samples are read in each iteration. Choosing the right size affects both performance and latency:
General guidelines:
Example for different use cases:
// Real-time ADS-B decoding (low latency needed)
let source = IqSource::from_file(path, freq, rate, 4096, format)?;
// General SDR processing (balanced)
let source = IqSource::from_file(path, freq, rate, 16384, format)?;
// Batch file processing (maximum throughput)
let source = IqSource::from_file(path, freq, rate, 65536, format)?;
RTL-SDR tips:
sudo modprobe rtl2832_sdr buffering=1SoapySDR tips:
PlutoSDR tips:
Different I/Q formats have different performance characteristics:
| Format | Bandwidth | Precision | Use Case |
|---|---|---|---|
| Cu8 | Lowest | 8-bit | RTL-SDR, bandwidth-limited scenarios |
| Cs8 | Low | 8-bit | Signed 8-bit devices |
| Cs16 | Medium | 16-bit | Higher dynamic range, HackRF |
| Cf32 | Highest | 32-bit | Pre-processed files, maximum precision |
Recommendation: Use the native format of your source when possible to avoid unnecessary conversions.
If the RTL kernel modules are installed you will need to temporarily unload them before using this library as follows:
sudo rmmod rtl2832_sdr
sudo rmmod dvb_usb_rtl28xxu
sudo rmmod rtl2832
sudo rmmod rtl8xxxu
Failure to do so will result in the following USB error:
thread 'main' panicked at 'Unable to open SDR device!: Usb(Busy)'
To list available RTL-SDR devices:
rtl_test
To list available SoapySDR devices:
SoapySDRUtil --find
If your device isn't detected, ensure the appropriate SoapySDR module is installed (e.g., SoapyRTLSDR, SoapyHackRF, SoapyLimeSDR).
To list available Adalm-Pluto devices:
iio_info -s
If you need I/Q samples for testing or development:
With RTL-SDR:
rtl_sdr -f 1090000000 -s 2400000 -n 24000000 adsb_sample.iq
With SoapySDR:
SoapySDRUtil --rate=2.4e6 --freq=1090e6 --output=adsb_sample.iq
Desperado supports raw I/Q files in various formats:
Contributions are welcome! Here are some ways you can help:
Please ensure:
cargo fmt, cargo clippy)cargo test --all-features)For major changes, please open an issue first to discuss the approach.
This project is licensed under the MIT License. See the license.md file for details.