Benchmarks¶
Wall time per feature on one 10 s clip at 22.05 kHz (a 220 Hz tone plus
white noise, float32), with the parameters of the bundled config.json.
Produced by
python benchmarks/bench_features.py --repeat 7 --librosa --torch-batch 16 --markdown
Each number is the median of 7 timed calls after one untimed warm-up; the
IQR column is the interquartile range of those 7 calls in ms. AFX's STFT
cache is cleared before every AFX call, so each feature pays for its own
transform. librosa runs with the same n_fft, hop_length and center
and with its default (disabled) cache. The torch column is one
AFXFeatureModule forward pass under torch.no_grad() on a (16, 220500)
float32 batch, divided by 16.
Machine: a 2 vCPU cloud VM, Intel Xeon Processor @ 2.10 GHz (model string
as reported by lscpu, 1 thread per core, 4 MiB L2 per core), Linux 6.18,
7 GB RAM. Python 3.13.16, afx-audio 0.3.0, NumPy 2.5.3, SciPy 1.18.1,
librosa 1.0.0, torch 2.14.1+cpu with 2 intra-op threads.
| Feature | AFX ms | IQR | librosa ms | librosa function | torch ms per clip (batch of 16) |
|---|---|---|---|---|---|
zcr |
2.14 | 0.31 | 5.25 | feature.zero_crossing_rate |
5.74 |
variance |
0.47 | 0.13 | |||
entropy |
16.60 | 3.46 | |||
crest_factor |
1.84 | 0.06 | |||
kurtosis |
0.76 | 0.04 | |||
autocorr_variance |
9.09 | 0.66 | |||
mobility |
1.10 | 0.02 | |||
complexity |
1.36 | 0.09 | |||
sample_entropy |
267.52 | 4.15 | |||
energy_ratio |
0.33 | 0.06 | |||
short_time_energy |
0.36 | 0.03 | |||
rms_energy |
0.36 | 0.02 | 0.08 | ||
spectral_centroid |
8.27 | 0.19 | 8.71 | feature.spectral_centroid |
5.88 |
spectral_bandwidth |
10.41 | 1.76 | 12.44 | feature.spectral_bandwidth |
6.86 |
spectral_rolloff |
9.57 | 0.36 | 8.91 | feature.spectral_rolloff |
7.88 |
spectral_contrast |
10.94 | 0.81 | 8.67 | feature.spectral_contrast |
18.71 |
spectral_entropy |
10.24 | 0.38 | 7.35 | ||
spectral_flatness |
9.39 | 0.44 | 6.74 | feature.spectral_flatness |
6.54 |
spectral_flux |
11.23 | 0.34 | 5.68 | ||
spectral_skewness |
12.36 | 0.54 | 10.26 | ||
spectral_slope |
9.16 | 0.17 | 7.38 | ||
spectral_kurtosis |
10.84 | 0.61 | 16.96 | ||
spectral_crest |
8.90 | 0.78 | 6.85 | ||
spectral_decrease |
9.32 | 0.40 | 5.91 | ||
melspectrogram |
9.75 | 0.43 | 8.26 | feature.melspectrogram |
5.85 |
mfcc |
9.98 | 0.62 | 8.48 | feature.mfcc |
6.14 |
mfcc_delta |
10.59 | 0.77 | 10.10 | feature.delta(mfcc) |
6.28 |
mfcc_delta_delta |
10.97 | 0.72 | 9.16 | feature.delta(mfcc, order=2) |
7.18 |
chroma_stft |
9.68 | 0.86 | 7.21 | feature.chroma_stft(tuning=0) |
5.53 |
chroma_cqt |
9.72 | 0.55 | 73.64 | feature.chroma_cqt * |
|
tonnetz |
9.60 | 1.02 | 7.45 | feature.tonnetz(chroma=chroma_stft) |
|
onset_strength |
9.98 | 0.50 | 8.25 | onset.onset_strength |
|
cqt |
9.46 | 0.34 | 21.82 | cqt * |
|
pitch |
19.81 | 0.54 | 22.98 | yin * |
|
thd |
3.71 | 0.18 | |||
hnr |
18.05 | 0.44 | |||
lpc |
11.93 | 0.48 | |||
formants |
46.31 | 2.99 | |||
gfcc |
9.69 | 0.48 | 6.36 | ||
| total | 621.81 | 136.18 (one module) |
extract_all_features on the same config, sharing one STFT per framing: 565.46 ms
Reading the table¶
Rows marked * are not the same computation. AFX's cqt and chroma_cqt
weight STFT bins with log-spaced triangles, so they cost one STFT; librosa
computes a true constant-Q transform with octave-wise filtering and
resampling, which is 2 to 8 times slower here and has a time resolution
that varies with frequency. pitch and librosa.yin implement the same
estimator but differ in how unvoiced frames are reported (see
librosa equivalence).
For the rows that are numerically equal to librosa, the two libraries are
within about 40% of each other (zcr aside), because both are dominated
by one real FFT over about 430 frames of 2048 samples. AFX also memoizes
the mel and gammatone filterbanks across calls; librosa rebuilds its mel
filterbank on every call.
sample_entropy is over 40% of the total. Its cost grows with the
square of the frame length in the worst case (Richman and Moorman, 2000), and the
bundled config computes it on frames of 1024 samples. Drop it, or use
shorter frames, when throughput matters.
extract_all_features reuses one STFT for features with the same
framing, centering and padding mode. With the bundled config that saves
about 55 ms of the 620 ms sum; the rest of each spectral feature's time is
the magnitude, power and per-feature reductions, which are not shared.
On this two-core machine the torch path runs most spectral features at
the same speed per clip as the NumPy path or up to 2 times faster
(spectral_flux 5.7 ms against 11.2 ms) by batching the FFT and matrix
products. spectral_contrast (a sort per octave band), spectral_kurtosis
and zcr are slower in torch. Expect the gap to change with core count and on a GPU; rerun the
command above on the target machine.
Variance¶
On a shared VM, single runs move by 10 to 30%: runs of the command above on the same machine gave 622 to 678 ms for the total. The IQR column shows the spread within one run. Compare libraries within one run of the script, not across runs or machines.