audio-codec
A collection of VoIP audio codecs implemented for Rust. This crate provides a unified interface for encoding and decoding various audio formats commonly used in SIP, VoIP, and WebRTC applications.
Supported Codecs
| Codec | Implementation | Feature | no_std |
|---|---|---|---|
| G.711 (PCMA/PCMU) | Pure Rust | Built-in | yes (heap-free) |
| G.722 | Pure Rust | Built-in | yes (heap-free) |
| G.729 | Pure Rust (g729-sys) |
Built-in | yes (heap-free) |
| Opus | Pure Rust (opus-rs) |
opus (on by default) |
yes (needs alloc) |
| Telephone Event | RFC 4733 | Built-in | yes (heap-free) |
| Resampler | Polyphase FIR | Built-in | yes (heap-free) |
Features
- Unified API: Simple
EncoderandDecodertraits for all codecs. no_stdsupport: every codec runs withoutstd. G.711/G.722/G.729, the resampler and telephone-event are fully heap-free (no allocator needed); Opus needs analloc(its internal working set is ~250 KB and is boxed).- Resampler: Built-in audio resampling utility.
Performance
Measured on Apple M2 Pro (processing 20ms audio frames):
| Codec | Encode (20ms) | Decode (20ms) | Rate |
|---|---|---|---|
| PCMU | ~50.09 ns | ~59.73 ns | 8kHz |
| PCMA | ~50.23 ns | ~59.63 ns | 8kHz |
| G.722 | ~5.02 µs | ~3.82 µs | 16kHz |
| G.729 | ~20.50 µs | ~6.16 µs | 8kHz |
| Opus | ~52.34 µs | ~23.19 µs | 48kHz |
Note: Benchmarks were run with cargo bench --bench codec_bench (Criterion). create_encoder(CodecType::Opus) currently uses the default Opus profile: 48kHz, stereo, Application::Audio, bitrate 64kbps, complexity 5.
Usage
Add this to your Cargo.toml:
[]
= "0.4" # Opus is enabled by default
To opt out of Opus (smaller build, no alloc needed):
[]
= { = "0.4", = false, = ["std"] }
Example: Decoding PCMA
use ;
Example: Encoding G.722
use ;
Example: Configuring Opus (Factory API)
use ;
no_std support
The crate works on bare-metal targets with no std. G.711/G.722/G.729, the
resampler and telephone-event are additionally heap-free (no allocator);
Opus needs an alloc because its encoder/decoder working set (~250 KB) is
boxed. Disable the default std feature and use the slice-based *_into API:
[]
= "0.4"
= false
use ;
Use max_encode_bytes / max_decode_samples to size the buffers correctly:
let needed_bytes = encoder.max_encode_bytes;
let needed_samples = decoder.max_decode_samples;
Resampler in no_std
Resampler borrows a caller-provided coefficient buffer (~24 KB):
use ;
let mut coeffs: = ;
let mut r = new?;
let mut out = ;
let n = r.resample_into?;
Opus in no_std
Opus also works without std (it needs an alloc — the encoder/decoder are
boxed). Use the slice-based *_into API exactly like the other codecs:
use ;
// 48 kHz, mono. The structs are boxed internally, so this only needs `alloc`.
let mut encoder = new;
let mut decoder = new;
let pcm: & = /* 20 ms @ 48 kHz = 960 mono samples */;
let mut packet = ;
let n = encoder.encode_into?;
let mut out = ;
let m = decoder.decode_into?;
Supported codecs in no_std
| Codec | Status |
|---|---|
| G.711 (PCMA/PCMU), G.722, G.729, Telephone Event | ✅ fully heap-free (no allocator) |
| Resampler | ✅ fully heap-free (borrowed coeffs buffer) |
| Opus | ✅ supported (needs alloc; encoder/decoder are boxed) |
The crate is verified to compile on thumbv7em-none-eabi and other bare-metal
targets. Float math (resampler + Opus) goes through libm when std is off.
License
This project is licensed under the MIT License.