Realistic telephone-channel data augmentation for training noise-robust STT/ASR models.
Simulates the full physical degradation chain a phone call goes through, in the correct order:
clean speech ─→ room (RIR) ─→ background/foreground noise @ random SNR
─→ 8 kHz + 300–3400 Hz bandpass ─→ codec (GSM/AMR/Opus/G.711/G.726)
─→ burst packet loss (Gilbert-Elliot) ─→ level perturbation
Every stage is backed by published evidence (see Why these defaults?).
pip install git+https://github.com/yentur/phone-augment.git # core (P2)
pip install "phone-augment[rir] @ git+https://github.com/yentur/phone-augment.git" # + room sim (P1)Requires ffmpeg on PATH (with libgsm/libopus; libopencore_amrnb optional —
missing codecs are auto-skipped and weights renormalized).
from phone_augment import PhoneAugment, AugmentConfig, NoiseBank, RIRPool
bank = NoiseBank("noises/") # MUSAN / ESC-50 / your own call backgrounds
# Pipeline 1 — full chain (room + telephony)
aug = PhoneAugment(bank, rir_pool=RIRPool.load("rir_pool.npz"))
# Pipeline 2 — pure telephony, no room sim (faster, no pyroomacoustics needed)
aug = PhoneAugment(bank, config=AugmentConfig.phone())
y, meta = aug(x) # x: mono float32 @16 kHz → y: degraded audio + full metadata
y, meta = aug(x, seed=42) # reproducible variantmeta records exactly what was applied:
{"rir": {"rt60": 0.59, "mic_dist_m": 0.34},
"noises": [{"type": "bg", "src": "rain.wav", "snr_db": 25.7}],
"bandpass_300_3400": true, "codec": "gsm-fr",
"packet_loss": {"rate": 0.149, "frames_lost": 45, "plc": false}}# 1) precompute a room pool once (makes the RIR stage ~free)
python -m phone_augment.rir --out rir_pool.npz --n 5000
# 2) augment a directory (multiprocessing)
phone-augment in_dir/ out_dir/ --noise-dir noises/ --rir-pool rir_pool.npz \
--pipeline p1 --variants 4 --workers 16 --out-sr 16000See examples/torch_dataset.py — fresh noise/SNR/codec
every epoch (per-epoch mixing), with a configurable share of clean samples.
P1 AugmentConfig() |
P2 AugmentConfig.phone() |
|
|---|---|---|
| Room simulation (RIR) | ✅ p=0.6 | ❌ |
| Noise + SNR / codec / packet loss | ✅ | ✅ |
| Extra dependency | pyroomacoustics |
— |
| Use when | calls include speakerphone / car / open office | close-talk phone calls |
| Stage | Evidence |
|---|---|
| Heavily-distorted codecs weighted up | −7.3…−12.8 abs WER on real telephony test sets (Vu et al., APSIPA 2019) |
| SNR: fg U(0,30) dB, bg U(10,40) dB | standard conventions (He et al. 2018); per-epoch remixing beats static (Braun et al.) |
| Burst (not individual) packet loss | −7 abs WER on real call centers (Fernández-Gallego & Toledano 2022) |
| RIR + point-source noise | simulated RIRs ≈ real once point noise added (Ko et al., ICASSP 2017) |
| Moving-noise as gain envelope, not moving-RIR | no demonstrated mono-ASR benefit from full moving-source simulation (SELD-only); a time-varying envelope captures the mono-audible effect |
| ~20% clean copies | noise-aug causes a small clean-set regression otherwise (Pranida et al. 2025) |
Anti-patterns (evidence says don't): inference-time denoising front-ends (hurt WER in 40/40 tested configs), 8k→16k bandwidth-extension front-ends, codec applied before downsampling.
- Noise mixing / bandpass / packet loss: ~10 ms per 10 s clip
- Codec round-trip (ffmpeg subprocess): ~80–250 ms → use
--workers Nor DataLoadernum_workers; 8 workers ≈ 50+ clips/s - RIR: precomputed pool ≈ free; on-the-fly ISM 50–300 ms per room
MIT