melpe-rs 0.1.2

MELPe vocoder (STANAG 4591) in pure Rust — 600 bps voice codec, no_std compatible
Documentation
# melpe-rs

Pure Rust implementation of the **MELPe** (Mixed Excitation Linear Prediction — enhanced) vocoder, conforming to **STANAG 4591** / **NATO narrowband voice coding**.

600 bps operation with superframe architecture. Zero heap allocation. `no_std` compatible for embedded/Xtensa targets.

## Features

- **600 bps codec** — 540 samples in, 6 bytes out (and back)
- **Superframe architecture** — 3 × 22.5 ms frames packed into a single 67.5 ms superframe
- **Full analysis chain** — pre-emphasis → LPC → LSF → pitch detection → bandpass voicing → quantization → bitstream packing
- **Full synthesis chain** — unpacking → dequantization → mixed excitation → all-pole filter → de-emphasis
- **Pure `core`** — no heap allocation in production code, all fixed-size arrays
- **Dual math backend** — native `f32` methods under `std`, [`libm`]https://crates.io/crates/libm under `no_std`

## Quick start

```rust
use melpe::encoder::Encoder;
use melpe::decoder::Decoder;
use melpe::core_types::{SUPERFRAME_SAMPLES, SUPERFRAME_BYTES_600};

let mut enc = Encoder::new();
let mut dec = Decoder::new();

// Audio in: 540 f32 samples at 8 kHz
let samples = [0.0f32; SUPERFRAME_SAMPLES];

// Encode: 540 samples → 6 bytes
let mut bitstream = [0u8; SUPERFRAME_BYTES_600];
enc.encode(&samples, &mut bitstream);

// Decode: 6 bytes → 540 samples
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
dec.decode(&bitstream, &mut output);
```

## Feature flags

| Flag | Default | Effect |
|------|---------|--------|
| `std` || Uses native `f32` math (hardware SIMD on x86_64) |
| `embedded` || `#![no_std]`, routes math through `libm` for bare-metal targets |

```sh
# Desktop / server (default)
cargo add melpe-rs

# Embedded / Xtensa / no_std
cargo add melpe-rs --no-default-features --features embedded
```

## Architecture

```
samples ──→ Encoder ──→ 6 bytes ──→ Decoder ──→ samples
             │                        │
             ├─ lpc.rs                ├─ bitstream.rs (unpack)
             ├─ pitch.rs             ├─ quantize.rs (dequantize)
             ├─ voicing.rs           ├─ voicing.rs (mixed excitation)
             ├─ quantize.rs          └─ synthesis.rs (all-pole filter)
             └─ bitstream.rs (pack)
```

### Modules

| Module | Purpose |
|--------|---------|
| `core_types` | Constants, frame geometry, superframe structures |
| `lpc` | Autocorrelation, Levinson-Durbin, LPC↔LSF conversion, Hamming window |
| `pitch` | Normalized autocorrelation pitch estimator with parabolic interpolation |
| `voicing` | 5-band bandpass filter bank, per-band voicing strength, mixed excitation |
| `quantize` | Scalar LSF/pitch/gain quantization, voicing collapse, LSF interpolation |
| `bitstream` | Bit-level packing/unpacking to 6-byte superframe format |
| `synthesis` | All-pole filter, de-emphasis, frame-level synthesis processor |
| `encoder` | Top-level encode: 540 samples → 6 bytes |
| `decoder` | Top-level decode: 6 bytes → 540 samples |
| `math` | `no_std` shim — `std``libm` dispatch for all floating-point intrinsics |

## Codec parameters

| Parameter | Value |
|-----------|-------|
| Sample rate | 8000 Hz |
| Frame size | 180 samples (22.5 ms) |
| Superframe | 3 frames, 540 samples (67.5 ms) |
| Bit rate | 600 bps |
| Bits per superframe | 41 |
| Bytes per superframe | 6 (48 bits, 7 spare) |
| LPC order | 10 |
| LSF count | 10 |
| Voicing bands | 5 (0–500, 500–1000, 1000–2000, 2000–3000, 3000–4000 Hz) |
| Pitch range | 20–160 samples (50–400 Hz) |

## Testing

```sh
# Full test suite (138 tests: 125 unit + 13 integration)
cargo test

# no_std subset (100 tests — core-only, no heap)
cargo test --lib --no-default-features --features embedded
```

## License

[MIT](LICENSE)