# AutoEQ: Automatic Equalization for Speakers, Headphones, and Rooms
## Introduction
AutoEQ is a Rust CLI toolkit for computing parametric EQ corrections. It uses global optimization algorithms to find optimal IIR filter parameters that minimize deviation from a target response or maximize perceptual preference scores.
**Note:** A graphical desktop application is available in a separate repository: [SotF](https://github.com/pierreaubert/sotf)
## Capabilities
### Supported Use Cases
- **Speaker EQ:** Optimize parametric EQ for loudspeakers using CEA2034/Spinorama measurements from [spinorama.org](https://spinorama.org)
- **Headphone EQ:** Generate EQ corrections for headphones targeting Harman curves or custom targets
- **Multi-Channel Systems:** Optimize stereo, 2.1, and multi-driver configurations with crossover management
- **Room Correction:** Multi-subwoofer alignment and Double Bass Array (DBA) optimization
### Optimization Algorithms
Three algorithm libraries are available:
| **NLopt** | ISRES, COBYLA, SLSQP, BOBYQA, DIRECT, StoGO, etc. | Nonlinear constraints |
| **Metaheuristics** | DE, PSO, RGA, TLBO, Firefly | Penalty-based |
| **AutoEQ Custom** | Adaptive Differential Evolution | Nonlinear constraints |
### Loss Functions
- `speaker-flat`: Minimize deviation from target curve (near-field listening)
- `speaker-score`: Maximize Harman/Olive preference score (far-field listening)
- `headphone-flat`: Flatten headphone response to target
- `headphone-score`: Optimize headphone preference score
- `drivers-flat`: Multi-driver crossover optimization
- `multi-sub-flat`: Multi-subwoofer array optimization
### PEQ Filter Models
- `pk`: All peak/bell filters (default)
- `hp-pk`: Highpass + peak filters
- `hp-pk-lp`: Highpass + peaks + lowpass
- `ls-pk-hs`: Low shelf + peaks + high shelf
- `free`: All filters can be any type
---
## AutoEQ CLI
The `autoeq` binary optimizes EQ for individual speakers or headphones.
### Basic Usage
```bash
# From spinorama.org API data
cargo run --bin autoeq --release -- \
--speaker="JBL M2" --version eac --measurement CEA2034 \
--algo nlopt:cobyla -n 7
# From local CSV file (format: frequency,spl)
cargo run --bin autoeq --release -- \
--curve measurements.csv --target harman.csv \
--algo autoeq:de -n 5
```
### Finding Speakers and Measurements
```bash
# List all speakers
curl http://api.spinorama.org/v1/speakers
# Get versions for a speaker
curl "http://api.spinorama.org/v1/speakers/JBL%20M2/versions"
# Get measurements for a speaker/version
curl "http://api.spinorama.org/v1/speakers/JBL%20M2/versions/eac/measurements"
```
### Key Parameters
| `-n, --num-filters` | 7 | Number of IIR filters |
| `--algo` | nlopt:cobyla | Optimization algorithm |
| `--loss` | speaker-flat | Loss function |
| `--peq-model` | pk | Filter structure model |
| `--min-freq` / `--max-freq` | 60 / 16000 | Frequency range for filters |
| `--min-q` / `--max-q` | 1 / 3 | Q factor limits |
| `--min-db` / `--max-db` | 1 / 3 | Gain limits (dB) |
| `--maxeval` | 2000 | Maximum optimizer evaluations |
| `--refine` | false | Run local refinement after global optimization |
### Algorithm Selection
```bash
# List all available algorithms
cargo run --bin autoeq --release -- --algo-list
# Recommended: global search + local refinement
cargo run --bin autoeq --release -- \
--algo nlopt:isres --refine --local-algo cobyla \
--speaker="KEF R3" --version asr --measurement CEA2034
```
### Differential Evolution Options
When using `autoeq:de`, additional parameters control the optimizer:
```bash
# List available strategies
cargo run --bin autoeq --release -- --strategy-list
# Use adaptive strategy
cargo run --bin autoeq --release -- \
--algo autoeq:de --strategy adaptivebin \
--adaptive-weight-f 0.8 --adaptive-weight-cr 0.7 \
--speaker="KEF R3" --version asr --measurement CEA2034
```
| `--strategy` | currenttobest1bin | DE mutation strategy |
| `--population` | 300 | Population size |
| `--tolerance` | 0.001 | Relative convergence tolerance |
| `--atolerance` | 0.0001 | Absolute convergence tolerance |
| `--recombination` | 0.9 | Crossover probability |
| `--seed` | random | Random seed for reproducibility |
### Headphone Example
```bash
cargo run --bin autoeq --release -- \
--curve headphone_measurement.csv \
--target harman-over-ear-2018.csv \
--loss headphone-score \
--algo mh:rga -n 5 --maxeval 20000 \
--min-freq 20 --max-freq 10000 --peq-model hp-pk-lp
```
---
## RoomEQ CLI
The `roomeq` binary optimizes multi-channel speaker systems with JSON configuration.
### Basic Usage
```bash
cargo run --bin roomeq --release -- --config room_config.json --output dsp_chain.json
```
### Features (v2)
- **Processing Modes:**
- `low_latency` (Mode A): IIR-only filters (< 5ms latency)
- `phase_linear` (Mode B): FIR filters for linear phase
- `hybrid` (Mode C): IIR for bass, FIR for mids/highs (best balance)
- **Bass Management:** Unified configuration for Single Sub, Multi-Sub (MSO), and Double Bass Array (DBA) strategies.
- **Advanced Calibration:**
- **Group Delay Optimization (GD-Opt):** Aligns subwoofer phase slope to mains.
- **Voice of God (VoG):** Timbre matches satellite channels to a reference.
- **Multi-Driver Speakers:** Active crossover optimization with polarity inversion testing.
### Configuration File Format (v2)
**2.1 System with Bass Management (Hybrid Mode):**
```json
{
"version": "1.2.0",
"system": {
"model": "stereo",
"speakers": {
"L": "left", "R": "right", "LFE": "sub"
},
"subwoofers": {
"config": "single",
"crossover": "bass_xo",
"sub": "L"
}
},
"crossovers": {
"bass_xo": {
"type": "LR24",
"frequency": 80.0
}
},
"speakers": {
"left": { "path": "measurements/left.csv" },
"right": { "path": "measurements/right.csv" },
"sub": { "path": "measurements/subwoofer.csv" }
},
"optimizer": {
"processing_mode": "hybrid",
"loss_type": "flat",
"algorithm": "autoeq:de",
"num_filters": 10,
"min_q": 0.5, "max_q": 10.0,
"min_db": -12.0, "max_db": 12.0,
"min_freq": 20.0, "max_freq": 20000.0,
"max_iter": 10000,
"gd_opt": {
"enabled": true,
"target_ms": 0.0
}
}
}
```
**Double Bass Array (DBA):**
```json
{
"version": "1.2.0",
"system": {
"model": "stereo",
"speakers": { "L": "l", "R": "r", "LFE": "dba" },
"subwoofers": {
"config": "dba",
"crossover": "dba_xo"
}
},
"crossovers": {
"dba_xo": { "type": "LR24", "frequency": 100.0 }
},
"speakers": {
"l": { "path": "left.csv" },
"r": { "path": "right.csv" },
"dba": {
"name": "DBA",
"front": [ { "path": "front_sub1.csv" }, { "path": "front_sub2.csv" } ],
"rear": [ { "path": "rear_sub1.csv" }, { "path": "rear_sub2.csv" } ]
}
},
"optimizer": {
"processing_mode": "low_latency"
}
}
```
### Output Schema
```bash
cargo run --bin roomeq --release -- --schema
```
---
## Development
### Prerequisites
Install [rustup](https://rustup.rs/) and [just](https://github.com/casey/just):
```bash
cargo install just
```
### Build Commands
```bash
just # List available commands
just prod # Build all release binaries
just prod-autoeq # Build autoeq only
just prod-roomeq # Build roomeq only
just dev # Build debug binaries
```
### Testing
Tests require the `AUTOEQ_DIR` environment variable:
```bash
export AUTOEQ_DIR=$(pwd)
# Run all tests
just test # cargo check + cargo test --workspace --lib
# Run tests with nextest (faster)
just ntest
# Run specific test
AUTOEQ_DIR=$(pwd) cargo test --lib test_name
# Run tests for a specific crate
AUTOEQ_DIR=$(pwd) cargo test -p autoeq --lib
AUTOEQ_DIR=$(pwd) cargo test -p autoeq-cea2034 --lib
```
### Fuzzing
Fuzz targets are in `autoeq/fuzz/fuzz_targets/`:
- `autoeq_config.rs`: Fuzzes configuration/CSV parsing
- `autoeq_csv.rs`: Fuzzes CSV input handling
To run fuzzing (requires nightly Rust and cargo-fuzz):
```bash
cargo install cargo-fuzz
cd autoeq
cargo +nightly fuzz run autoeq_csv
```
### Quality Assurance
The QA suite runs optimization scenarios with regression thresholds:
```bash
just qa
```
This executes predefined scenarios testing:
- Speaker optimization (flat and score loss)
- Headphone optimization (multiple algorithms)
- Various PEQ models and algorithm combinations
Each scenario has a `--qa <threshold>` flag that fails if the final loss exceeds the threshold.
Individual QA targets:
```bash
just qa-ascilab-6b # Speaker with score loss
just qa-jbl-m2-flat # Speaker with flat loss
just qa-jbl-m2-score # Speaker with score loss
just qa-beyerdynamic-dt1990pro # Headphone tests
just qa-edifierw830nb # Multiple algorithm comparison
```
### Benchmarking
```bash
# Download speaker data from spinorama.org
just download
# Run algorithm benchmarks
just bench-autoeq-speaker
# Run convergence benchmarks
just bench-convergence
```
### Code Quality
```bash
just fmt # Format code
cargo check --workspace --all-targets
cargo clippy --workspace --all-targets
```
---
## Contributing
- Open an issue on [GitHub](https://github.com/pierreaubert/sotf)
- Send a PR