CallCleaner
Lightweight bioacoustic denoising from an audio foundation model.
CallCleaner removes background noise (wind, rain, vehicles, other animals) from recordings of animal vocalizations. It is a 19M-parameter waveform-to-waveform model that needs no detector, text prompt or GPU, and runs about 90脳 faster than real time on a laptop CPU.
Project page 路 Paper (arXiv, link coming) 路 Code (GitHub)
How it was made
The source-separation foundation model SAM-Audio (facebook/sam-audio-small), prompted with
"animal sound" and with time spans from a simple animal voice-activity detector, removes more noise
from animal calls than dedicated bioacoustic denoisers, but it is slow and inherits detector errors.
CallCleaner distills it into a small model:
- Architecture: the Demucs denoiser from Biodenoising
(
biodenoising16k_dns48, 16 kHz, mono), initialized from Biodenoising's weights. - Teacher: SAM-Audio with VAD-span prompts. Its target stream is the pseudo-label; its residual stream is a noise estimate. Half of each batch is remixed (another segment's residual added to a pseudo-label), as in bootstrapped remixing.
- Data: 4 s segments (1.8 h) from the public corpora Biodenoising was trained on (DCASE few-shot bioacoustics, Orchive and five bird corpora), none shared with its benchmark.
- Training: 2,000 steps.
On Biodenoising's benchmark (47 clips 脳 4 SNRs), CallCleaner leaves 11 dB less noise around the call than Biodenoising, the leading neural bioacoustic denoiser with public weights, and among fast, CPU-capable systems it pushes the Pareto frontier of noise removal vs. call fidelity. See the paper for full results.
Usage
pip install biodenoising safetensors huggingface_hub librosa soundfile
import librosa, soundfile as sf, torch
from biodenoising.denoiser.pretrained import biodenoising16k_dns48
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file
model = biodenoising16k_dns48(pretrained=False)
model.load_state_dict(load_file(hf_hub_download("malper/CallCleaner", "model.safetensors")))
model.eval()
y, _ = librosa.load("noisy.wav", sr=16000, mono=True) # the model works at 16 kHz, mono
with torch.no_grad():
clean = model(torch.tensor(y)[None, None])[0, 0, : len(y)].numpy()
sf.write("clean.wav", clean, 16000)
For long recordings, process overlapping chunks (e.g. 60 s with a 1 s cross-fade); the command-line script in the code repository does this, and handles folders and other sample rates.
Limitations
- Output is 16 kHz: content above 8 kHz (e.g. many bat and some bird and insect calls) is not restored.
- Trained to keep one caller's vocalizations; overlapping calls from other animals may be treated as noise.
- Distilled from a teacher that can miss quiet calls or keep loud non-target sounds; it inherits some of these errors. Listen to outputs before using them for analysis.
License
The weights are a derivative of SAM-Audio and are released under the SAM License (see LICENSE); by using or redistributing them you agree to its terms. The Biodenoising architecture and initialization are MIT-licensed.
Citation
@article{xie2026callcleaner,
title = {CallCleaner: Lightweight Bioacoustic Denoising from an Audio Foundation Model},
author = {Xie, Michael and Begu{\v{s}}, Ga{\v{s}}per and Alper, Morris},
year = {2026}
}
- Downloads last month
- -