drone-propulsion-audio-cnn

A small multi-task CNN over log-mel spectrograms of drone propulsion audio, trained as a methodology baseline: the deliverable is not the accuracy, it is the gap between evaluation protocols.

Four heads, all from a 2 s / 16 kHz window:

head classes
presence silence, drone
drone drone1, drone2
throttle low, high
dist 25 cm, 50 cm

1.18 M parameters. Trained on a single RTX 5090 in 3.1 min.

The result that matters

Same architecture, same data, same hyperparameters β€” only the train/test split changes.

protocol presence drone throttle dist what it measures
naive_window 0.948 1.000 1.000 0.999 leaky β€” adjacent windows of one recording land on both sides
by_run 0.420 0.967 0.959 0.919 no window sharing; same drone/distance/throttle/mic seen in training
by_mic 0.797 0.846 0.988 0.868 unseen microphone placement
by_distance 0.479 0.814 0.988 – unseen distance / SNR regime

Random-window splitting reports drone at 1.000. Holding out whole recordings drops it to 0.967, and holding out a microphone configuration drops it to 0.846. Nothing about the model changed. The first number is an artefact of adjacent 2 s windows straddling the split β€” the model is re-identifying a recording, not recognising a drone.

This matters because published drone-acoustics results are frequently reported under the first protocol.

The two targets do not degrade the same way

This is the more useful half of the result. Under the two genuine distribution shifts β€” an unseen microphone and an unseen distance β€” the heads come apart:

head naive by_mic by_distance
drone (identity) 1.000 0.846 0.814
throttle (RPM proxy) 1.000 0.988 0.988

Throttle holds at ~0.99 through both shifts. Drone identity falls to 0.846 / 0.814.

That is what the physics predicts. Throttle sets rotational speed, which sets the blade-pass frequency and its harmonic comb β€” a spectral position, and a different microphone at a different distance still sees the same position. Unit identity leans on timbre, relative harmonic weighting and channel colouration, all of which the microphone and the propagation path change.

Practical reading: RPM-linked targets transfer across rigs; identity-linked targets need the microphone and the geometry inside the training distribution. If you are choosing what to build first from a propulsion-audio rig, the regression target is the safer product.

Caveat on the presence head

presence is poorly conditioned here and its numbers should not be read as a detection result. The corpus has 144 drone recordings against 24 silence recordings, and the silence ones are shorter (~31 s vs ~91 s) β€” roughly an 18:1 window imbalance, trained with unweighted cross-entropy. Under by_run only ~17 silence recordings remain in training and the head becomes unstable (0.420 macro-F1). This is a class-imbalance artefact, not evidence about leakage. Fixing it needs class weighting and more silence, not a different split.

Comparison β€” learned features vs. hand-crafted auditory features

Mobley, Campbell & Rasband (Classification of SUAS propellers with auditory feature extraction methods, NOISE-CON 2023) classify four small-UAS propellers from Timbre-Toolbox descriptors plus MOSQITO sound-quality metrics fed to a random decision forest, and find acoustic roughness to be the single most discriminative feature. Their evaluation is a random split at a fixed 50 ft radius.

We rebuilt that kind of feature vector β€” 30 descriptors, MOSQITO roughness/loudness/sharpness plus reimplemented Timbre-Toolbox temporal and spectral descriptors β€” and ran it through the same four protocols as the CNN. features.py and train_features.py are in this repo.

model naive drone naive throttle by_run drone by_run throttle by_mic drone by_mic throttle by_dist drone by_dist throttle
CNN (log-mel) 1.000 1.000 0.967 0.959 0.846 0.988 0.814 0.988
RF (30 features) 0.990 0.998 0.943 0.982 0.345 0.564 0.627 0.811
RF (level features dropped) 0.978 0.986 0.942 0.924 0.353 0.566 0.631 0.660

In distribution the two are equivalent β€” the forest matches or beats the CNN under by_run (0.982 vs 0.959 on throttle).

Under a microphone change the forest collapses and the CNN does not: throttle 0.564 vs 0.988, drone 0.345 vs 0.846.

It is not an absolute-level artefact. Dropping the four level-carrying descriptors (level_db, level_a_db, loudness, spec_energy) changes nothing (0.566 on throttle). The reason is that the descriptors themselves are microphone-dependent β€” 12 of 30 shift by more than one pooled standard deviation between the training microphones and the held-out one:

descriptor Cohen's d
spec_spread +2.02
spec_rolloff85 +1.73
level_db -1.45
spec_flatness +1.40
am_depth -1.32
sharpness +1.31

A forest splits on absolute thresholds and has no machinery to absorb that shift; the CNN sees a normalised spectrogram and was trained with SpecAugment and Β±6 dB gain jitter.

Note what sits in that list: roughness (-1.14) and sharpness (+1.31) β€” the two MOSQITO metrics the NOISE-CON feature ranking leans on hardest. Their result stands for a fixed measurement chain, but a roughness threshold learned on one microphone should not be expected to hold on another. For a rig with a microphone arc, where each position is a different physical transducer, that is worth testing before trusting.

Caveat: the forest was fitted on 2424 windows against the CNN's 18798 β€” roughness costs ~2 s of CPU per 2 s window, which caps how densely it can be sampled. It is not data-starved in distribution (it reaches 0.943 under by_run), but the comparison is not perfectly matched.

Side result β€” why a smarter split does not rescue a single-instance dataset

orhanyaman/Propeller is the dataset behind the only published paper that classifies propellers by blade count from sound. It is five files β€” one continuous recording per class (2/3/4/5/6 blades, underwater, ~5–6 min each).

Same CNN, two protocols:

protocol macro-F1
random windows 0.983
time-block (first 70 % trains, last 30 % tests) 0.950

The gap is only +0.032 β€” and that is the point. With one physical propeller per class, train and test come from the same propeller, same session, same hydrophone, no matter how you cut the time axis. Both numbers measure "can you re-identify this recording", not "can you recognise a four-blade propeller". A single-instance dataset cannot be fixed with a better split; it can only be fixed with more physical instances.

Data

DroneAudioSet drone-only subset (MIT), NeurIPS 2025 Datasets & Benchmarks. A full factorial: 2 drones Γ— 2 distances Γ— 2 throttle levels Γ— 3 mic configs Γ— (6 runs + 1 silence) = 168 recordings, 16 kHz, 30–152 s each.

Note the dataset's own purpose is drone audition β€” a microphone on board the drone, detecting humans underneath. There the drone is the noise. Here it is the signal, which is a different task than the one the authors benchmark.

Channel 0 only. The 8array-* configs ship 8 channels, soundskrit ships 1; taking ch0 everywhere keeps one comparable stream across mic configs.

Intended use

A template and a sanity check, not a production detector. It exists to establish, before a partner lab's own measurements arrive, that:

  1. the evaluation protocol dominates the reported number;
  2. throttle level (a proxy for RPM) is recoverable from steady-state propulsion audio;
  3. an unseen microphone placement is a real distribution shift, not a formality.

Do not use it to detect drones in the field. Two drone identities at 25–50 cm in a controlled setting is not a field distribution.

Training details

  • Features: log-mel, 128 mels, n_fft 1024, hop 160, 20 Hz–8 kHz, computed on GPU.
  • Augmentation: SpecAugment (2 freq + 2 time masks) and Β±6 dB gain jitter. No pitch or time-stretch augmentation β€” pitch shift moves the blade-pass frequency, which is the throttle label; augmenting it away trains the model to ignore the target.
  • AdamW, OneCycle, 12 epochs, bf16 autocast.
  • Loss is masked per head, so silence windows train presence only.

Released weights are the by_run checkpoint, so the by_run row above is this checkpoint's own score.

Usage

import torch, torchaudio
from huggingface_hub import hf_hub_download

state = torch.load(hf_hub_download("makromaksym/drone-propulsion-audio-cnn", "model.pt"), map_location="cpu")
# Architecture: see train.py (SmallCNN) in the Files tab.

train.py, prepare.py, data_mod.py, features.py, train_features.py and propeller_bladecount.py are in the Files tab β€” the split protocols live in data_mod.py.

Full project, including the briefing this came out of: https://github.com/dontriskit/ars-lab-drone-audio

Limitations

  • Two drone identities. drone here is closer to "which of these two units" than to drone typing.
  • Binary throttle, not measured RPM. No tachometer ground truth in this dataset.
  • 16 kHz. Propeller harmonics extend past 8 kHz; this ceiling is inherited from the source data.
  • Single channel. The mic-array geometry is discarded.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Dataset used to train makromaksym/drone-propulsion-audio-cnn