Expand description
§Desperado
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.
§What are I/Q Samples?
I/Q (In-phase/Quadrature) samples are the fundamental representation of radio signals in software-defined radio (SDR). They represent complex numbers where:
- I (In-phase): The real component, representing the signal along the cosine axis
- Q (Quadrature): The imaginary component, representing the signal along the sine axis
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.).
§Installation
Add Desperado to your Cargo.toml:
[dependencies]
desperado = "0.1"§With SDR device support
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§Available features
rtlsdr: RTL-SDR device support (DVB-T dongles)soapy: SoapySDR device support (HackRF, LimeSDR, etc.)pluto: Adalm-Pluto SDR support
The following features are only needed for examples:
clap: Command-line argument parsing for exampleswaterfall: Waterfall plot visualization exampleaudio: FM demodulation examples with audio output
§Projects using desperado
- jet1090 - Real-time ADS-B decoder for tracking aircraft
- ship162 - AIS decoder for tracking maritime vessels
If you’re using Desperado in your project, feel free to open a PR to add it here!
§Usage
§Basic example (synchronous version)
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(())
}§RTL-SDR (async version)
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(())
}§More data sources
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.
- The
rtlsdrfeature enables support for RTL-SDR devices (DVB-T dongles). It is based on thertl-sdr-rscrate which is a pure Rust implementaiton of the RTL-SDR driver. - The
soapyfeature enables support for SoapySDR-compatible devices (HackRF, LimeSDR, BladeRF, etc.). It is based on thesoapysdrcrate which provides Rust bindings to the SoapySDR C++ library. The SoapySDR library must be installed separately. - The
plutofeature enables support for Adalm-Pluto devices. It is based on thepluto-sdrcrate 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.
§Sync vs Async: Which should I use?
Desperado provides both synchronous (IqSource) and asynchronous (AsyncIqSource) interfaces. Here’s how to choose:
Use Synchronous (IqSource) when:
- Processing files offline: Reading recorded I/Q files for analysis
- Simple applications: You don’t need concurrent operations
- Blocking is acceptable: Your application can wait for I/O
- Easier to reason about: Simpler control flow
Use Asynchronous (AsyncIqSource) when:
- Real-time processing: Working with live SDR devices
- Concurrent operations: Processing multiple streams simultaneously
- Non-blocking required: Your application must remain responsive
- Integrating with async ecosystem: Using tokio, async-std, etc.
Performance note: For single-threaded file processing, synchronous can be faster due to less overhead. For real-time SDR applications, async is typically better.
§Performance Tuning
§Chunk Size Selection
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:
- Small chunks (1K-4K samples): Lower latency, more overhead, good for interactive applications
- Medium chunks (8K-16K samples): Balanced performance, recommended for most applications
- Large chunks (32K-64K samples): Better throughput, higher latency, good for batch processing
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)?;§Hardware SDR Performance
RTL-SDR tips:
- Sample rates above 2.4 MS/s may cause USB bandwidth issues
- Use manual gain instead of AGC for better performance
- On Linux, consider increasing USB buffer size:
sudo modprobe rtl2832_sdr buffering=1
SoapySDR tips:
- Check device-specific documentation for optimal buffer sizes
- Some devices benefit from specific stream arguments
- Monitor for dropped samples with verbose logging
PlutoSDR tips:
- Buffer sizes should match your processing requirements
- Network latency affects performance for IP-connected devices
- Use USB 3.0 connections when possible
§Format Considerations
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.
§Troubleshooting
§RTL-SDR kernel modules (Linux)
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 rtl8xxxuFailure to do so will result in the following USB error:
thread 'main' panicked at 'Unable to open SDR device!: Usb(Busy)'§RTL-SDR Device Detection
To list available RTL-SDR devices:
rtl_test§SoapySDR Device Detection
To list available SoapySDR devices:
SoapySDRUtil --findIf your device isn’t detected, ensure the appropriate SoapySDR module is installed (e.g., SoapyRTLSDR, SoapyHackRF, SoapyLimeSDR).
§Adalm-Pluto Device Detection
To list available Adalm-Pluto devices:
iio_info -s§Finding I/Q Sample Files
If you need I/Q samples for testing or development:
§Public Datasets
- IQEngine - Public repository of RF recordings with metadata
- Signal Identification Wiki - Sample files for various signal types
§Capturing Your Own
With RTL-SDR:
rtl_sdr -f 1090000000 -s 2400000 -n 24000000 adsb_sample.iqWith SoapySDR:
SoapySDRUtil --rate=2.4e6 --freq=1090e6 --output=adsb_sample.iq§File Formats
Desperado supports raw I/Q files in various formats:
- Cu8 (Complex unsigned 8-bit): Most common for RTL-SDR, 2 bytes per sample
- Cs8 (Complex signed 8-bit): 2 bytes per sample
- Cs16 (Complex signed 16-bit): 4 bytes per sample, common for SoapySDR/Pluto
- Cf32 (Complex 32-bit float): 8 bytes per sample, high precision
§Contributing
Contributions are welcome! Here are some ways you can help:
- Add SDR device support: HackRF, LimeSDR, BladeRF, etc.
Consider pure Rust implementations where possible! - Improve documentation: Fix typos, add examples, clarify explanations
- Report bugs: Open an issue with details and reproduction steps
- Add tests: Help improve test coverage
- Share your project: Using Desperado? Add it to the “Projects Using Desperado” section!
Please ensure:
- Code follows Rust conventions (
cargo fmt,cargo clippy) - All tests pass (
cargo test --all-features) - New features include documentation and tests
For major changes, please open an issue first to discuss the approach.
§License
This project is licensed under the MIT License. See the license.md file for details.
§API Naming Conventions
This library follows consistent naming conventions:
- Synchronous types:
IqSource,IqRead,RtlSdrReader, etc. - Asynchronous types:
IqAsyncSource,IqAsyncRead,AsyncRtlSdrReader, etc. - Async types are prefixed with
Asyncor useIqAsyncnaming - All async operations return
Futures or implement theStreamtrait
Re-exports§
Modules§
Structs§
- Gain
Element - Individual gain element configuration
Enums§
- Device
Config - Gain
- Unified gain configuration across all SDR devices
- Gain
Element Name - Gain element identifier
- IqAsync
Source - Asynchronous I/Q Data Source (streamable)
- IqFormat
- I/Q Data Format
- IqSource
- Synchronous I/Q Data Source (iterable)
Functions§
- expanduser
- Expand tilde (~) in path to home directory
- parse_
si_ value - Parse a numeric value with optional SI suffix (k, M, G)