# dsp-testing > Guide Claude on testing strategies for DSP code, epsilon comparisons, and benchmark patterns. Use when writing tests for audio processing, verifying signal behavior, or benchmarking DSP performance. - Author: Matthew Maxwell - Repository: maxwellmattryan/eden - Version: 20260202231114 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/maxwellmattryan/eden - Web: https://mule.run/skillshub/@@maxwellmattryan/eden~dsp-testing:20260202231114 --- --- name: dsp-testing description: Guide Claude on testing strategies for DSP code, epsilon comparisons, and benchmark patterns. Use when writing tests for audio processing, verifying signal behavior, or benchmarking DSP performance. --- # DSP Testing ## Why DSP Testing is Hard 1. **Floating point arithmetic** - Results vary by platform, compiler, and optimization level 2. **Transient behavior** - Filters need time to settle before measurements are valid 3. **Non-determinism** - Oscillators with random phase, noise generators produce different output each run 4. **Precision requirements** - Audio needs ~96 dB dynamic range but small errors accumulate 5. **Real-time constraints** - Tests must verify allocation-free operation ## Cardinal Rules 1. **Use epsilon comparisons** - Never exact equality for floats 2. **Seed all randomness** - Pass `Some(seed)` to oscillators/LFOs for reproducibility 3. **Skip transients** - Wait 2-3 cycles before measuring filter output 4. **Test both f32 and f64** - Generic blocks need both verified 5. **Test edge cases** - Zero input, silence, DC, Nyquist, denormals ## Epsilon Guidelines | Measurement | Epsilon (f32) | Epsilon (f64) | |-------------|---------------|---------------| | Sample values | `1e-6` | `1e-12` | | Gain/amplitude | `1e-4` | `1e-10` | | Phase (radians) | `1e-5` | `1e-11` | | Frequency (Hz) | `0.01` | `1e-6` | | dB measurements | `0.1` | `0.01` | | Intermediate smoothing | `0.01` | `0.001` | ```rust fn approx_eq(a: f32, b: f32, epsilon: f32) -> bool { (a - b).abs() < epsilon } fn approx_eq_relative(a: S, b: S) -> bool { let epsilon = S::EPSILON.to_f64() * a.to_f64().abs().max(b.to_f64().abs()).max(1.0); (a.to_f64() - b.to_f64()).abs() < epsilon } ``` ## Quick Reference | Topic | Reference | |-------|-----------| | Block tests, fixtures, f32/f64 coverage | [unit-testing.md](unit-testing.md) | | Frequency/impulse response, transients | [signal-verification.md](signal-verification.md) | | Criterion setup, SIMD vs scalar | [benchmarking.md](benchmarking.md) | | Integration tests, multi-block chains | [graph-testing.md](graph-testing.md) | ## Common Test Tolerances ```rust const SAMPLE_EPSILON: f32 = 1e-6; const SILENCE_THRESHOLD: f32 = 1e-5; // ~-100 dB const CLIPPING_THRESHOLD: f32 = 2.0; // Allow headroom before flagging const AMPLITUDE_TOLERANCE: f32 = 0.05; // 5% for oscillator overshoot ``` ## See Also - [dsp-engineering](../dsp-engineering/SKILL.md) - Implementation patterns - [dsp-mathematics](../dsp-mathematics/SKILL.md) - Theory behind frequency/impulse response